# Welcome

Hyperstack is a Ruby-based DSL and modern web toolkit for building spectacular, interactive web applications fast!

* **One language** throughout the client and server. All Ruby code is compiled by [Opal](https://opalrb.com/) into JavaScript automatically.
* Webpacker and Yarn tooling for a **modern, fast hot-reloader build environment with Ruby source maps**.
* A well documented and stable Ruby DSL for wrapping **React** and **ReactRouter** as well as **any** JavaScript library or component. No need to learn JavaScript!
* **Isomorphic Models with bi-directional data** so you can access your models as if they were on the client.

All that means you can write simple front-end code like this:

```ruby
class GoodBooksToRead < Hyperstack::Component
  render(UL) do
    Book.good_books.each do |book|
      LI { "Read #{book.name}" }.on(:click) { display book } if book.available?
    end
  end
end
```

In the code above, if the `good_books` scope changed (even on the server), the UI would update automatically. That's the magic of React and Isomorphic Models with bi-directional data at work!

## Website and Documentation

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true)

While we have over 1000 specs passing in 3 different configurations, and several large apps using Hyperstack, documentation is lagging. If you see this icon it means we are working hard to get the docs up to the same state as the code.

Chapters without the work-in-progress flag are still draft, and any issues are greatly appreciated, or better yet follow the `Edit on Github` link, make your proposed corrections, and submit a pull request.

## Setup and installation

You can be up and running in **less than 5 minutes**. Just follow the simple setup guide for a new Rails application all correctly configured and ready to go with Hyperstack.

* Setup and Installation: <https://docs.hyperstack.org/rails-installation>

Beyond the installation we strongly suggest new developers work trough the [todo tutorial](https://docs.hyperstack.org/tutorial). As it gives a minimal understanding of the Hyperstack framework.

## Community and support

Hyperstack is supported by a friendly, helpful community, both for users, and contributors. We welcome new people, please reach out and say hello.

* Reach us at: [Slack chat](https://join.slack.com/t/hyperstack-org/shared_invite/enQtNTg4NTI5NzQyNTYyLWQ4YTZlMGU0OGIxMDQzZGIxMjNlOGY5MjRhOTdlMWUzZWYyMTMzYWJkNTZmZDRhMDEzODA0NWRkMDM4MjdmNDE)

## Roadmap

We are currently driving towards our 1.0 release. Currently we are at 1.0.alpha1.5 release candidate. There is a list of 163 open issues including some bugs, documentation issues and many requested enhancements. The plan is to triage the issues and do a weekly release until the issues are closed or deemed not needed for a 1.0 release.

Please consider contributing by grabbing a "good first issue", or just adding your thoughts, thumbs up, or down on any issues that interest you.

## Contributing

In general, if you would like to help in any way, please read the [CONTRIBUTING](https://github.com/hyperstack-org/hyperstack/blob/edge/CONTRIBUTING.md) file for suggestions.\
System setup for the development of Hyperstack itself is documented in this file.

## Links

* Rubygems: <https://rubygems.org/profiles/hyperstack>
* Travis: <https://travis-ci.org/hyperstack-org>
* Website edge: <https://edge.hyperstack.org/>
* Website master: <https://hyperstack.org/>

## License

Hyperstack is developed and released under the MIT License. See the [LICENSE](https://github.com/hyperstack-org/hyperstack/blob/edge/LICENSE) file for further details.


# Rails Installation and Configuration

The easiest way to get the full benefit of Hyperstack is to integrate it with a Rails application.

Adding Hyperstack to your existing Rails App is as simple as adding the gem and running the installer.

Continue to the next section to make sure you have the necessary prerequisites on your machine.

[**For more info on why we use Rails**](/rails-installation/why-rails)


# Prerequisites

### Rails

Hyperstack is currently tested on Rails \~> 5.0 and \~> 6.0.

> If you are on Rails 4.0 it might be time to upgrade, but that said you probably can manually install Hyperstack on Rails 4.0 and get it working.

[Rails Install Instructions](http://railsinstaller.org/en)

### Yarn

For a full system install including webpacker for managing javascript assets you will need yarn. To skip adding webpacker use `hyperstack:install:skip-webpack` when installing Hyperstack.

[Yarn Install Instructions](https://yarnpkg.com/en/docs/install#mac-stable)

### Database

To fully utilize Hyperstack's capabilities you will be need an SQL database that has an ActiveRecord adapter. If you have a choice we have found Postgresql works best (and it also deploys to Heroku without issue.) If you are new to Rails, then the default Sqlite database (which rails will install) will work fine.

> Why don't we support NoSql databases? The biggest reasons are security and effeciency. Hyperstack access-policies are based on known table names and attributes and after-commit hooks. Keep in mind that modern DBs support the json and jsonb attribute types allowing you to add arbitrary json based data to your database.

## Creating a New Rails App

If you don't have an existing Rails app you can create a new Rails app with the following command line:

```
rails new NameOfYourApp -T
```

To avoid much pain do not name your app `Application` as this will conflict with all sorts of things in Rails and Hyperstack.

Once you have created the app cd into the newly created directory.

> The -T option will skip adding minitest directories as Hyperstack prefers RSpec. However if you have an existing app with minitest that is okay too.


# Using the Hyperstack Installer

In the directory of your existing or newly created Rails app:

* add `gem 'rails-hyperstack', "~> 1.0.alpha1.0"` to your `Gemfile`
* run `bundle install`
* run `bundle exec rails hyperstack:install`

> Note: if you want to use the unreleased edge branch your gem specification will be:
>
> ```ruby
> gem 'rails-hyperstack',
>      git: 'git://github.com/hyperstack-org/hyperstack.git',
>      branch: 'edge',
>      glob: 'ruby/*/*.gemspec'
> ```
>
> **HOWEVER currently we are doing weekly alpha updates, you should not need to do this.**

## Start the Rails app

* `bundle exec foreman start` to start Rails and the Hotloader
* Navigate to `http://localhost:5000/`

You will see an empty page with the word "App" displayed.

Open your editor and find the file `/app/hyperstack/components/app.rb`

Change the `'App'` to `'Hello World'` and save the file.

You should see the page on the browser change to "Hello World"

You are in business!

> If this does not work, please contact us on [*slack*](https://hyperstack.org/slack), or [**create an issue on github.**](https://github.com/hyperstack-org/hyperstack/issues/new)

## Installer Options

You can control what gets installed with the following options:

```
bundle exec rails hyperstack:install:webpack          # just add webpack
bundle exec rails hyperstack:install:skip-webpack     # all but webpack
bundle exec rails hyperstack:install:hyper-model      # just add hyper-model
bundle exec rails hyperstack:install:skip-hyper-model # all but hyper-model
bundle exec rails hyperstack:install:hotloader        # just add the hotloader
bundle exec rails hyperstack:install:skip-hotloader   # skip the hotloader
```

> Note that the `:webpack` and `:skip-webpack` options control whether the installer will add the webpacker Gem. If webpacker is already installed in the Gemfile then the installer will always integrate with webpacker.


# Using the Generators

As well as the installer Hyperstack includes two generators to create basic component skeletons.

## Summary:

```
bundle exec rails g hyper:component ComponentName # add a new component
bundle exec rails g hyper:router RouterName # add a new router component
```

both support the following flags:

* `--no-help` don't add extra comments and method examples
* `--add-route=...` add a route to this component to the Rails routes file
* `--base-class=...` change the base class name from the default

## The Component Generator

To add a new component skeleton use the `hyper:component` generator:

```
bundle exec rails g hyper:component ComponentName
```

### File directories and Name Spacing Components

The above will create a new class definition for `MyComponent` in a file named `my_component.rb` and place it in the `app/hyperstack/components/` directory. The component may be name spaced and will be placed in the appropriate subdirectory. I.e. `Foo::BarSki` will generate `app/hyperstack/components/foo/bar_ski.rb`

### The `--no-help` flag

By default the skeleton will be verbose and contain examples of the most often used class methods which you can keep or delete as needed. You can generate a minimal component with the `--no-help` flag.

## Router Generator

Typically your top level component will be a *Router* which will take care of dispatching to specific components as the URL changes. This provides the essence of a *Single Page App* where as the user moves between parts of the application the URL is updated, the *back* and *forward* buttons work, but the page is **not** reloaded from the server.

A component becomes a router by including the `Hyperstack::Router` module which provides a number of methods that will be used in the router component.

To generate a new router skeleton use the `hyper:router` generator:

```
bundle exec rails g hyper:router App
```

> Note that in any Single Page App there will be two routers in play. On the server the router is responsible dispatching each incoming HTTP request to a controller. The controller will deliver back (usually using a view) the contents of the request.
>
> In addition on a Single Page App you will have a router running on the client, which will dispatch to different components depending on the current value of the URL. The server is only contacted if the current URL leaves the set of URLs that client router knows how to deal with.

### Adding a Route to the Rails `routes.rb` File

When you generate a new component you can use the `--add-route` option to add the route for you. For example:

```
bundle exec rails g hyper:router MainApp \
                    --add-route="/(*others)"
```

will add

```ruby
  get '/(*others)', to: 'hyperstack#main_app'
```

to the Rails `routes.rb` file, which will direct all URLS to the `MainApp` component.

For details see [**Routing and Mounting Components.**](/rails-installation/routing-and-mounting-components)

### Specifying the Base Class

By default components will inherit from the `HyperComponent` base class.

You can globally override this by changing the value `Hyperstack.component_base_class` in the `hyperstack.rb` initializer.

For example some teams prefer `ApplicationComponent` as their base class name.

You can also override the base class name when generating a component using the `--base-class` option.

This is useful when you have a common library subclass that other classes will inherit from. For example:

```
bundle exec rails g hyper:component UserBio --base-class=TextArea
```

will generate

```
class UserBio < TextArea
...
end
```


# File Structure

Hyperstack adds the following files and directories to your Rails application:

```
/app/hyperstack
/app/operations
/app/policies
/config/initializers/hyperstack.rb
/app/javascript/packs/client_and_server.js
/app/javascript/packs/client_only.js
```

In addition there are configuration settings in existing Rails files that are explained in the next section. Below we cover the purpose of each these files, and their contents.

## The `/app/hyperstack/` Directory

Here lives all your Hyperstack code that will run on the client. Some of the subdirectories are *isomorphic* meaning the code is shared between the client and the server, other directories are client only.

Within the `hyperstack` directory there can be the following sub-directories:

* `components` *(client-only)* is where your components live.

  > Following Rails conventions a component with a class of `Bar::None::FooManchu` should be in a file named `components/bar/none/foo_manchu.rb`
* `models` *(isomorphic)* is where ActiveRecord models are shared with the client. More on this below.
* `operations` *(isomorphic)* is where Hyperstack Operations will live.
* `shared` *(isomorphic)* is where you can put shared code that are not models or operations.
* Any other subdirectory (such as `libs` and `client-ops`) will be considered client-only.

## Sharing Models and Operations

Files in the `hyperstack` `/models` and `/operations` directories are loaded on the client *and* the server. So when you place a model's class definition in the `hyperstack/models` directory the class is available on the client.

Assuming:

```ruby
# app/hyperstack/models/todo.rb
class Todo < ApplicationRecord
  ...
end
```

Then

```
  Todo.count # will return the same value on the client and the server
```

> See the Policy section below for how access to the actual data is controlled. Remember a Model *describes* some data, but the actual data is stored in the database, and protected by Policies.

Likewise Operations placed in the `/operations` directory can be run on the client or the server, or in the case of a `ServerOp` the operation can be invoked on the client, but will run on the server.

Hyperstack sets things up so that Rails will first look in the `hyperstack` `/models` and `/operations` directories, and then in the server only `app/models` and `app/operations` directories. So if you don't want some model shared you can just leave it in the normal `app` directory.

## Splitting Class Definitions

There are cases where you would like split a class definition into its shared and server-only aspects. For example there may be code in a model that cannot be sensibly run on the client. Hyperstack augments the Rails dependency lookup mechanism so that when a file is found in a `hyperstack` directory we will *also* load any matching file in the normal `app` directory.

This works because Ruby classes are *open*, so that you can define a class (or module) in multiple places.

## Server Side Operations

Operations are Hyperstack's way of providing *Service Objects*: classes that perform some operation not strictly belonging to a single model, and often involving other services such as remote APIs. *The idea of Operations comes from the* [*Trailblazer Framework.*](https://trailblazer.to/2.0/gems/operation/2.0/index.html)

As such Operations can be useful strictly on the server side, and so can be added to the `app/operations` directory.

Server side operations can also be remotely run from the client. Such operations are defined as subclasses of `Hyperstack::ServerOp`.

The right way to define a `ServerOp` is to place its basic definition including its parameter signature in the `hyperstack/operations` directory, and then placing the rest of the operation's definition in the `app/operations` directory.

## Policies

Hyperstack uses Policies to define access rights to your models. Policies are placed in the `app/policies` directory. For example the policies for the `Todo` model would defined by the `TodoPolicy` class located at `app/policies/todo_policy.rb` Details on policies can be found [Policy section of this document.](https://docs.hyperstack.org/isomorphic-dsl/hyper-policy).

## Example Directory Structure

```
└── app/
    ├── models/
    │   └── user.rb # private section of User model
    ├── operations/
    │   └── email_the_owner.rb # server code
    ├── hyperstack/
    │   ├── components/
    │   │   ├── app.rb
    │   │   ├── edit_todo.rb
    │   │   ├── footer.rb
    │   │   ├── header.rb
    │   │   ├── show_todo.rb
    │   │   └── todo_index.rb
    │   ├── models/
    │   │   ├── application_record.rb # usually no need to split this
    │   │   ├── todo.rb # note all of Todo definition is public
    │   │   └── user.rb # user has a public and private section
    │   └── operations/
    │       └── email_the_owner.rb # serverop interface only
    └── policies/
        ├── todo_policy.rb
        └── user_policy.rb
```

These directories are where most of your work will be done during Hyperstack development.

> ### What about Controllers and Views?
>
> Hyperstack works alongside Rails controllers and views. In a clean-sheet Hyperstack app you never need to create a controller or a view. On the other hand if you have existing code or aspects of your project that you feel would work better using a traditional MVC approach everything will work fine. You can also merge the two worlds: Hyperstack includes two helpers that allow you to mount components either from a controller or from within a view.

## The Hyperstack Initializer

The Hyperstack configuration can be controlled via the `config/initializers/hyperstack.rb` initializer file. Using the installer will set up a reasonable set of of options, which you can tweak as needed.

Here is a summary of the various configuration settings:

```ruby
# config/initializers/hyperstack.rb

# server_side_auto_require will patch the ActiveSupport Dependencies module
# so that you can define classes and modules with files in both the
# app/hyperstack/xxx and app/xxx directories.  

require "hyperstack/server_side_auto_require.rb"

# By default the generators will generate new components as subclasses of
# HyperComponent.  You can change this using the component_base_class setting.

Hyperstack.component_base_class = 'HyperComponent' # i.e. 'ApplicationComponent'

# prerendering is default :off, you should wait until your
# application is relatively well debugged before turning on.

Hyperstack.prerendering = :off # or :on

# The transport setting controls how push (websocket) communications are
# implemented.  The default is :none, but will be set to :action_cable if you
# install hyper-model.

# Other possibilities are :action_cable, :pusher (see www.pusher.com)
# or :simple_poller which is sometimes handy during system debug.

Hyperstack.transport = :action_cable # :pusher, :simple_poller or :none

# hotloader settings:
# sets the port hotloader will listen on.  Note this must match the value used
# to start the hotloader typically in the foreman Procfile.
Hyperstack.hotloader_port = 25222
# seconds between pings over the hotloader websocket.  Normally not needed.
Hyperstack.hotloader_ping = nil
# hotloader will automatically reload callbacks when effected classes are
# reloaded.  Not recommended to change this.
Hyperstack.hotloader_ignore_callback_mapping = false

# Transport settings
# seconds before timeout when sending messages between the rails console and  
# the server.
Hyperstack.send_to_server_timeout = 10

# Transport specific options
Hyperstack.opts, {
  # pusher specific options
  app_id: 'your pusher app id',
  key: 'your pusher key',
  secret: 'your pusher secret',
  cluster: 'mt1', # pusher cluster defaults to mt1
  encrypted: true, # encrypt pusher comms, defaults to true
  refresh_channels_every: 2.minutes, # how often to check which channels are alive

  # simple poller specific options
  expire_polled_connection_in: 5.minutes, # when to kill simple poller connections
  seconds_between_poll: 5.seconds, # how fast to poll when using simple poller
  expire_new_connection_in: 10.seconds, # how long to keep initial sessions alive
}

# Namespace used to keep hyperstack communication separate from other websockets
Hyperstack.channel_prefix = 'synchromesh'

# If there a JS console available should websocket comms be logged?
Hyperstack.client_logging = true

# Automatically create a (possibly temporary) websocket connection as each
# browser session starts.  Usually this is needed for further authentication and
# should be left as true
Hyperstack.connect_session =  true

# Where to store the connection tables.  Default is :active_record but you
# can also specify redis.  If specifying redis the redis url defaults to
# redis://127.0.0.1:6379
Hyperstack.connection = [adapter: :active_record] # or
                      # [adapter: :redis, redis_url: 'redis://127.0.0.1:6379]

# The import directive loads optional portions of the various hyperstack gems.
# Here are the common imports typically included:

Hyperstack.import 'hyperstack/hotloader', client_only: true if Rails.env.development?

# and these are typically not imported:

# React source is normally brought in through webpacker
# Hyperstack.import 'react/react-source-browser'

# add this line if you need jQuery AND ARE NOT USING WEBPACK
# Hyperstack.import 'hyperstack/component/jquery', client_only: true

# The following are less common settings which you should never have to change:
Hyperstack.prerendering_files = ['hyperstack-prerender-loader.js']
Hyperstack.public_model_directories = ['app/hyperstack/models']


# change definition of on_error to control how errors such as validation
# exceptions are reported on the server
module Hyperstack
  def self.on_error(operation, err, params, formatted_error_message)
    ::Rails.logger.debug(
      "#{formatted_error_message}\n\n" +
      Pastel.new.red(
        'To further investigate you may want to add a debugging '\
        'breakpoint to the on_error method in config/initializers/hyperstack.rb'
      )
    )
  end
end if Rails.env.development?
```

## Hyperstack Packs

Rails `webpacker` organizes javascript into *packs*. Hyperstack will look for and load one of two packs depending on if you are prerendering or not.

The default content of these packs are as follows:

```javascript
//app/javascript/packs/client_and_server.js
// these packages will be loaded both during prerendering and on the client
React = require('react');                         // react-js library
createReactClass = require('create-react-class'); // backwards compatibility with ECMA5
History = require('history');                     // react-router history library
ReactRouter = require('react-router');            // react-router js library
ReactRouterDOM = require('react-router-dom');     // react-router DOM interface
ReactRailsUJS = require('react_ujs');             // interface to react-rails
// to add additional NPM packages run `yarn add package-name@version`
// then add the require here.
```

```javascript
//app/javascript/packs/client_only.js
// add any requires for packages that will run client side only
ReactDOM = require('react-dom');               // react-js client side code
jQuery = require('jquery');                    // remove if you don't need jQuery
// to add additional NPM packages call run yarn add package-name@version
// then add the require here.
```


# Routing and Mounting Components

Within a Rails Application there are three ways to render or *mount* a component on a page:

* Route directly to the component from the rails `routes.rb` file.
* Render a component directly from a controller.
* Render a component from within a layout or view file.

## Routing Directly to Components

Components can be directly mounted from the Rails `routes.rb` file, using the builtin Hyperstack controller.

For example a Rails `routes.rb` file containing

```ruby
  get 'some_page/(*others)', to: 'hyperstack#some_component'
```

will route all urls beginning with `some_page` to `SomeComponent`.

When you generate a new component you can use the `--add-route` option to add the route for you (see the previous section.)

Note that typically the Rails route will be going to a Router Component. That is why we typically add the wild card to the Rails route so that all urls beginning with `some_page/` will all be handled by `SomeComponent` without having to reload the page.

Also note that for the purposes of the example we used rather dubious names, a more logical setup would be:

```ruby
  get `/(*others)`, to 'hyperstack#app'
```

Which you could generate with

```
bundle exec rails g hyper:router App --add-route="/(*others)"
```

You could also divide your application into several single page apps, for example

```ruby
...
  get 'admin/(*others)', to: 'hyperstack#admin'
  get '/(*others)', to: 'hyperstack#app'
...
```

would route all URLS beginning with admin to the `Admin` component, and everything else to the main `App` component. *Note that order of the routes is important as Rails will dispatch to the first route it matches.*

> If the component is named spaced separate each module with a double underscore (`__`) and leave the module names CamelCase:
>
> ```ruby
>   get 'admin/(*others)', to: 'hyperstack#Admin__App'
> ```

## Rendering a Component from a Controller

To render a component from a controller use the `render_component` helper:

```ruby
  render_component 'Admin', {user_id: params[:id]}, layout: 'admin'
  # would pass the user_id to the Admin component and use the admin layout

  # in general:
  render_component 'The::Component::Name'
                   { ... component params ... },
                   { other render params such as layout }
```

Only the component name is required, but note that if you want to have other render params, you will have to supply at least an empty hash for the component params.

## Rendering (or Mounting) a Component from a View

To mount a component directly in a view use the mount\_component view helper:

```markup
   <%= mount_component 'Clock' %>
```

Like render\_component may take params which will be passed to the mounted component.

Mounting a component in an existing view, is a very useful way to integrate Hyperstack into existing applications. You mount a component to serve a specific function such as a dynamic footer or a tweeter feed onto an existing view without having to do a major redesign.


# Other Rails Configuration Details

Hyperstack internally sets a number of Rails configurations as outlined below.

> These are all setup automatically by the hyperstack generators and installers. They are documented here for advanced configuration or in the sad chance that something gets broken during your setup. Please report any issues with setup, or if you feel you have to manually tweak things.

## Require the `hyperstack-loader`

The `app/assets/javascripts/application.js` file needs to require the hyperstack-loader.

```javascript
//= require hyperstack-loader // add as the last require directive
```

The loader handles bringing in client side code, getting it compiled (using sprockets) and adding it to the webpacks (if using webpacker.)

> Note that now that Rails is using webpacker by default you may have to create this file, and the single line above. If so be sure to checkout your layout file, as the javascript\_include\_tag will also be missing there.

## `app/assets/config/manifest.js`

If you are using webpacker this file must exist and contain the following line:

```ruby
//= link_directory ../javascripts .js
```

This line insures that the any javascript in the assets directory are included in the webpacks. In older versions of Rails, this line will already be there, and if not using webpacker its actually not necessary (but doesn't hurt anything.)

## The application layout

If using a recent version of rails with webpacker you may find that the application.html.erb file no longer loads the application.js file. Make sure that your layout file has this line:

```markup
   <%= javascript_include_tag 'application' %>
```

## Required NPM modules

If using Webpacker Hyperstack needs the following NPM modules:

```
yarn 'react', '16'
yarn 'react-dom', '16'
yarn 'react-router', '^5.0.0'
yarn 'react-router-dom', '^5.0.0'
yarn 'react_ujs', '^2.5.0'
yarn 'jquery', '^3.4.1'   # this is only needed if using jquery
yarn 'create-react-class'
```

## Routing

If using hyper-model you need to mount the Hyperstack engine in the routes file like this:

```ruby
# config/routes.rb
Rails.application.routes.draw do
  # this route should be first in the routes file so it always matches'
  mount Hyperstack::Engine => '/hyperstack' # you can use any path you choose
  ...
```

To directly route from a URL to a component you can use the builtin Hyperstack controller with a route like this:

```ruby
  get "hyperstack-page/(*others)", "hyperstack#comp_name"
```

Where `comp_name` is the underscored name of the component you want to mount. I.e. `MyComp` becomes `my_comp`. The `/(*others)` indicates that all routes beginning with `hyperstack-page/` will be matched, if that is your desired behavior.

> Note that the engine mount point can be any string you wish but the controller routed to above is always `hyperstack`.

## Other Rails Configuration Settings

Hyperstack will by default set a number of Rails configuration settings. To disable this set

```ruby
  config.hyperstack.auto_config = false
```

In your Rails application.rb configuration file.

Otherwise the following settings are automatically applied in test and staging:

```ruby
# This will prevent any data transmitted by HyperOperation from appearing in logs
config.filter_parameters << :hyperstack_secured_json

  # Add the hyperstack directories
  config.eager_load_paths += %W(#{config.root}/app/hyperstack/models)
  config.eager_load_paths += %W(#{config.root}/app/hyperstack/models/concerns)
  config.eager_load_paths += %W(#{config.root}/app/hyperstack/operations)
  config.eager_load_paths += %W(#{config.root}/app/hyperstack/shared)

  # But remove the outer hyperstack directory so rails doesn't try to load its
  # contents directly
  delete_first config.eager_load_paths, "#{config.root}/app/hyperstack"
```

but in production we autoload instead of eager load.

```ruby
  # add the hyperstack directories to the auto load paths
  config.autoload_paths += %W(#{config.root}/app/hyperstack/models)
  config.autoload_paths += %W(#{config.root}/app/hyperstack/models/concerns)
  config.autoload_paths += %W(#{config.root}/app/hyperstack/operations)
  config.autoload_paths += %W(#{config.root}/app/hyperstack/shared)

  # except for the outer hyperstack directory
  delete_first config.autoload_paths, "#{config.root}/app/hyperstack"
```


# Why Rails? Other Frameworks?

## Why Rails?

Rails provides a robust, tried and true tool chain that takes care of much of the day to day details of building your app. Hyperstack builds on the Rails philosophy of convention over configuration, meaning that there is almost no boiler plate code in your Rails-Hyperstack application. Almost every line that you write for your Hyperstack application will deal with the application requirements. We have seen real reductions of up to 400% in the lines of code needed to deliver high quality functionality.

People sometimes balk at Rails because when they see the huge number of files and directories generated by the Rails installer, it looks crazy, complex, and ineffecient. Keep in mind that this has very little if any impact on your application's performance, and when developing code 90% of your time will be spent in the following directories: `app/models` and `app/hyperstack`. The rest of the files are there to hold configuration files, and seldom used content, so they have a place out of the way of your main development activities.

Developers often believe that Rails modules like ActionController and ActiveRecord while powerful are slow. In the case of Hyperstack this is largely irrelevant since one of our goals is to offload as much work to the client as possible. For example rather than have a multitude of controllers delivering different page views and updates, your client side Hyperstack code is now responsible for that. The role of the server becomes the central database, and the place where secure operations are executed (such as sending mail, authenticating users etc.)

## How about other Rack Frameworks?

But still you may have specific needs for a lighter weight system, or have an existing Sinatra app (for example) that you would like to use with Hyperstack. For now we will say it's in the plan, and it's just a matter of time. If you are interested leave a comment on this issue: <https://github.com/hyperstack-org/hyperstack/issues/340>


# HyperComponent

Your Hyperstack Application is built from a series of *Components* which are Ruby Classes that display portions of the UI. Hyperstack Components are implemented using [React](https://reactjs.org/), and can interoperate with existing React components and libraries. Here is a simple example that displays a ticking clock:

```ruby
# Components inherit from the HyperComponent base class
# which supplies the DSL to translate from Ruby into React
# function calls
class Clock < HyperComponent
  # Components can be parameterized.
  # in this case you can override the default
  # with a different format
  param format: "%m/%d/%Y %I:%M:%S"
  # After_mount is an example of a life cycle method.
  after_mount do
    # Before the component is first rendered (mounted)
    # we setup a periodic timer that will update the  
    # current_time instance variable every second.
    # The mutate method signals a change in state
    every(1.second) { mutate @current_time = Time.now }
  end
  # every component has a render block which describes what will be
  # drawn on the UI
  render do
    # Components can render other components or primitive HTML or SVG
    # tags.  Components also use their state to determine what to render,
    # in this case the @current_time instance variable
    DIV { @current_time.strftime(format) }
  end
end
```

The following chapters cover these aspects and more in detail.


# Component Classes

The Hyperstack Component DSL is a set of class and instance methods that are used to describe React components and render the user-interface.

The following sections give a brief orientation to the structure of a component and the methods that are used to define and control its behavior.

## Defining a Component

Hyperstack Components are Ruby classes that inherit from the `HyperComponent` base class:

```ruby
class MyComponent < HyperComponent
  ...
end
```

> [**More on the HyperComponent base class**](/client-dsl/notes#the-hypercomponent-base-class)

## The `render` Callback

At a minimum every *concrete* component class must define a `render` block which generates one or more child elements. Those children may in turn have an arbitrarily deep structure. [**More on concrete and abstract components...**](/client-dsl/notes#abstract-and-concrete-components)

```ruby
class Component < HyperComponent
  render do
    DIV { } # render an empty div
  end
end
```

> The code between `do` and `end` and { .. } are called blocks. [**More here...**](/client-dsl/notes#blocks-in-ruby)

To save a little typing you can also specify the top level element to be rendered:

```ruby
class Component < HyperComponent
  render(DIV, class: 'my-special-class') do
    # everything will be rendered in a div
  end
end
```

To create a component instance, you reference its class name as a method call from another component. This creates a new instance, passes any parameters and proceeds with the component lifecycle.

> [**The actual type created is an Element, read on for details...**](/client-dsl/notes#component-instances)

```ruby
class FirstComponent < HyperComponent
  render do
    NextComponent() # ruby syntax requires either () or {} following the class name
  end
end
```

> While a component is defined as a class, and a rendered component is an instance of that class, we do not in general use the `new` method, or need to modify the components `initialize` method.

### Invoking Components

> Note: when invoking a component **you must have** a (possibly empty) parameter list or (possibly empty) block.
>
> ```ruby
> MyCustomComponent()  # ok
> MyCustomComponent {} # ok
> MyCustomComponent    # <--- breaks
> ```

## Component Params

A component can receive params to customize its look and behavior:

```ruby
class SayHello < HyperComponent
  param :to
  render(DIV, class: :hello) do
    "Hello #{to}!"
  end
end

...

  SayHello(to: "Joe")
```

Components can receive new params, causing the component to update. [**More on Params ...**](/client-dsl/params).

## Component State

Components also have *state*, which is stored in instance variables. You signal a state change using the `mutate` method. Component state is a fundamental concept covered [**here**](/client-dsl/state).

## Life Cycle Callbacks

A component may be updated during its life time due to either changes in state or receiving new params. You can hook into the components life cycle using the the life cycle methods. Two of the most common lifecycle methods are `before_mount` and `after_mount` that are called before a component first renders, and just after a component first renders respectively.

```ruby
class Clock < HyperComponent
  param format: "%m/%d/%Y %I:%M:%S"
  after_mount do
    every(1.second) { mutate @current_time = Time.now }
  end
  render do
    DIV { @current_time.strftime(format) }
  end
end
```

The complete list of life cycle methods and their syntax is discussed in detail in the [**Lifecycle Methods**](/client-dsl/lifecycle-methods) section.

## Events, Event Handlers, and Component Callbacks

Events such as mouse clicks trigger callbacks, which can be attached using the `on` method:

```ruby
class ClickCounter < HyperComponent
  before_mount { @clicks = 0 }
  def adverb
    @clicks.zero? ? 'please' : 'again'
  end
  render(DIV) do
    BUTTON { "click me #{adverb}" }
    .on(:click) { mutate @clicks += 1 } # attach a callback
    DIV { "I've been clicked #{pluralize(@clicks, 'time')}" } if @clicks > 0
  end
end
```

This example also shows how events and state mutations work together to change the look of the display. It also demonstrates that because a HyperComponent is just a Ruby class you can define helper methods, use conditional logic, and call on predefined methods like `pluralize`.

In addition components can fire custom events, and make callbacks to the upper level components. [**More details ...**](/client-dsl/events-and-callbacks)

## Application Structure

Your Application is built out of many smaller components using the above features to control the components behavior and communicate between components. To conclude this section let's create a simple Avatar component which shows a profile picture and username using the Facebook Graph API.

```ruby
class Avatar < HyperComponent
  param :user_name

  render(DIV) do
    # for each param a method with the same name is defined
    ProfilePic(user_name: user_name)
    ProfileLink(user_name: user_name)
  end
end

class ProfilePic < HyperComponent
  param :user_name

  # note that in Ruby blocks can use do...end or { ... }
  render { IMG(src: "https://graph.facebook.com/#{user_name}/picture") }
end

class ProfileLink < HyperComponent
  param :user_name
  render do
    A(href: "https://www.facebook.com/#{user_name}") do
      user_name
    end
  end
end
```


# HTML Tags & CSS Classes

## HTML elements

Each Hyperstack component renders a series of HTML (and SVG) elements, using Ruby expressions to control the output.

```ruby
UL do
  5.times { |n| LI { "Number #{n}" }}
end
```

For example

```ruby
DIV(class: 'green-text') { "Let's gets started!" }
```

would create the following HTML:

```markup
<div class="green-text">Let's gets started!</div>
```

And this would render a table:

```ruby
TABLE(class: 'ui celled table') do
  THEAD do
    TR do
      TH { 'One' }
      TH { 'Two' }
      TH { 'Three' }
    end
  end
  TBODY do
    TR do
      TD { 'A' }
      TD(class: 'negative') { 'B' }
      TD { 'C' }
    end
  end
end
```

[**See the predefined tags summary for the complete list of HTML and SVG elements.**](/client-dsl/predefined-tags)

## Naming Conventions

To distinguish between HTML and SVG tags, builtin components and application defined components the following naming conventions are followed:

* `ALLCAPS` denotes a HTML, SVG or builtin React psuedo components such as `FRAGMENT`.
* `CamelCase` denotes an application defined component class like `TodoList`.

## HTML parameters

You can pass any expected parameter to a HTML or SVG element:

```ruby
A(href: '/') { 'Click me' } # <a href="/">Click me</a>
IMG(src: '/logo.png')  # <img src="/logo.png">
```

Each key-value pair in the parameter block is passed down as an attribute to the tag as you would expect.

## CSS

You can specify the CSS `class` on any HTML element.

```ruby
P(class: 'bright') { }
... or
P(class: :bright) { }
... or
P(class: [:bright, :blue]) { } # class='bright blue'
```

For `style` you need to pass a hash using the [**React style conventions**](https://reactjs.org/docs/dom-elements.html#style)**:**

```ruby
P(style: { display: item[:some_property] == "some state" ? :block : :none })
```

## Complex Arguments

You can pass multiple hashes which will be merged, and any individual symbols (or strings) will be treated as `=true`. For example

```ruby
A(:flag, {href: '/'}, class: 'my_class')
```

will generate

```markup
<a flag=true href='/' class='myclass'></a>
```

> [**more on passing hashes to methods**](/client-dsl/notes#ruby-hash-params)


# Component Children, Keys and Fragments

## Children

Components often have child components. If you consider HTML tags like `DIV`, `UL`, and `TABLE` you will see you are already familiar with this concept:

```ruby
DIV(id: 1) do
  SPAN(class: :span_1)  { 'hi' }
  SPAN(class: :span_2) { 'there' }
end
```

Here we have a `DIV` that receives one param, an id equal to 1 and has two child *elements* - the two spans.

The `SPAN`s each have one param (its css class) and has one child *element* - a string to render.

Hopefully at this point the DSL is intuitive to read, and you can see that this will generate the following HTML:

```markup
<div id=1>
  <span class='first_span'>hi</span>
  <span class='second_span'>there</span>
</div>
```

## Dynamic Children

Children do not have to be statically generated. Let's sort a string of text into individual word counts and display it in a list:

```ruby
# assume text is a string of text
UL do
  word_count(text).each_with_index do |word, count|
    LI { "#{count} - #{word}" }
  end
end
```

In this case you can see that we don't determine the actual number or contents of the `LI` children until runtime.

> [**The `word_count` method...**](/client-dsl/notes#word-count-method)
>
> Dynamically generating components creates a new concept called ownership. [**More here...**](/client-dsl/notes#ownership)

## Keys

In the above example what would happen if the contents of `text` were dynamically changing? For example if it was associated with a text box that the user was typing into, and we updated `text` whenever a word was entered.

In this case as the user typed new words, the `word_count` would be updated and the list would change. However actually only the contents of one of the list items (`LI` blocks) would actually change, and perhaps the sort order. We don't need to redraw the whole list, just the one list item that changed, and then perhaps shuffle two of the items. This is going to be much faster than redrawing the whole list.

Like React, Hyperstack provides a special `key` param that can identify child elements so that the rendering engine will know that while the content and order may change on some children, it can easily identify the ones that are the same:

```ruby
    LI(key: word) { "#{count} - #{word}"}
```

You don't have to stress out too much about keys, its easy to add them later. Just keep the concept in mind when you are generating long lists, tables, and divs with many children.

> [**More on how Hyperstack generates keys...**](/client-dsl/notes#generating-keys)

## Rendering Children

Application defined components can also receive and render children. A component's `children` method returns an enumerable that is used to access the *unrendered* children of a component. The children can then be rendered using the `render` method which will merge any additional parameters and render the child.

```ruby
class Indenter < HyperComponent
  render(DIV) do
    IndentLine(by: 10) do # see IndentLine below
      DIV {"Line 1"}
      DIV {"Line 2"}
      DIV {"Line 3"}
    end
  end
end

class IndentLine < HyperComponent
  param by: 20, type: Integer

  render(DIV) do
    children.each_with_index do |child, i|
      child.render(style: {"margin-left" => by*i})
    end
  end
end
```

## Rendering Multiple Values and the FRAGMENT component

A render block may generate multiple values. React assumes when a Component generates multiple items, the item order and quantity may change over time and so will give a warning unless each element has a key:

```ruby
class ListItems < HyperComponent
  render do
    # without the keys you would get a warning
    LI(key: 1) { 'item 1' }
    LI(key: 2) { 'item 2' }
    LI(key: 3) { 'item 3' }
  end
end

# somewhere else:
   UL do
     ListItems()
   end
```

If you are sure that the order and number of elements will not change over time you may wrap the items in the `FRAGMENT` pseudo component:

```ruby
class ListItems < HyperComponent
  render(FRAGMENT) do
    LI { 'item 1' }
    LI { 'item 2' }
    LI { 'item 3' }
  end
end
```


# Component Params

The `param` class method gives *read-only* access to each of the params passed to the component. Params are accessed as instance methods of the component.

> In React params are called `props`, but Hyperstack uses the more common Rails term `param`.

Within a component class the `param` method is used to define the parameter signature of the component. You can think of params as the values that would normally be sent to the instance's `initialize` method, but with the difference that a component will get new parameters during its lifecycle.

The param declaration has several options providing a default value, expected type, and an internal alias name.

Examples:

```ruby
param :foo # declares that we must provide a parameter foo when the component is instantiated or re-rerendered.
param :foo => "some default"        # declares that foo is optional, and if not present the value "some default" will be used.
param foo: "some default"           # same as above using ruby 1.9 JSON style syntax
param :foo, default: "some default" # same as above but uses explicit default key
param :foo, type: String            # foo is required and must be of type String
param :foo, type: [String]          # foo is required and must be an array of Strings
param foo: [], type: [String]       # foo must be an array of strings, and has a default value of the empty array.
param :foo, alias: :something       # the alias name will be used for the param (instead of foo)
```

### Accessing param values

Params are accessible in the component as instance methods. For example:

```ruby
class Hello < HyperComponent
  # visitor has a default value (so its not required)
  # and must be of type (i.e. instance of) String
  param visitor: "World", type: String

  render do
    "Hello #{visitor}"
  end
end
```

## Param Validation

As your app grows it's helpful to ensure that your components are used correctly.You do this by specifying the expected ruby class of your parameters. When an invalid value is provided for a param, a warning will be shown in the JavaScript console. Note that for performance reasons type checking is only done in development mode. Here is an example showing typical type specifications:

```ruby
class ManyParams < HyperComponent
  param :an_array,         type: [] # or type: Array
  param :a_string,         type: String
  param :array_of_strings, type: [String]
  param :a_hash,           type: Hash
  param :some_class,       type: SomeClass # works with any class
  param :a_string_or_nil,  type: String, allow_nil: true
end
```

Note that if the param has a type but can also be nil, add `allow_nil: true` to the specification.

## Default Param Values

You can define default values for your `params`:

```ruby
class ManyParams < HyperComponent
  param :an_optional_param, default: "hello", type: String, allow_nil: true
```

If no value is provided for `:an_optional_param` it will be given the value `"hello"`, it may also be given the value `nil`.

Defaults can be provided by the `default` key or using the syntax `param foo: 12` which would default `foo` to 12.

## Component Instances as Params

You can pass an instance of a component as a `param` and then render it in the receiving component.

```ruby
class Reveal < HyperComponent
  param :content
  render do
    BUTTON { "#{@show ? 'hide' : 'show'} me" }
    .on(:click) { mutate @show = !@show }
    content.render if @show
  end
end
class App < HyperComponent
  render do
    Reveal(content: DIV { 'I came from the App' })
  end
end
```

[see the spec...](https://github.com/hyperstack-org/hyperstack/blob/24131990ea1cdacfc9efc328d4994a7c2d86a0f4/docs/specs/spec/client-dsl/params_spec.rb#L4-L25)

`render` is used to render the child components. [**For details ...**](/client-dsl/component-details#rendering-children)

> Notice that this is just a way to pass a child to a component but instead of sending it to the "block" with other children you are passing it as a single named child.

## Other Params

A common type of component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element.

To do this use the `others` method which will gather all the params you did not declare into a hash. Then you can pass this hash on to the child component

```ruby
class CheckLink < HyperComponent
  others :attributes
  render do
    # we just pass along any incoming attributes
    A(attributes) { '√ '.span; children.each &:render }
  end
end

  # elsewhere
  CheckLink(href: "/checked.html")
```

Note: `others` builds a hash, so you can merge other data in or even delete elements out as needed.

## Aliasing Param Names

Sometimes we can make our component code more readable by using a different param name inside the component than the owner component will use.

```ruby
class Hello < HyperComponent
  param :name
  param include_time: true, alias: :time?
  render { SPAN { "Hello #{name}#{'the time is '+Time.now if time?}" } }
end
```

This way we can keep the interface very clear, but keep our component code short and sweet.

## Updating Params

Each time a component is rendered any of the components it owns may be re-rendered as well **but only if any of the params will change in value.** If none of the params change in value, then the owned-by component will not be rerendered as no parameters have changed.

Hyperstack determines if a param has changed through a simple Ruby equality check. If `old_params == new_params` then no update is needed.

For strings, numbers and other scalar values equality is straight forward. Two hashes are equal if they each contain the same number of keys and if each key-value pair is equal to the corresponding elements in the other hash. Two arrays are equal if they contain the same number of elements and if each element is equal to the corresponding element in the other array.

For other objects unless the object defines its own equality method the objects are equal only if they are the same instance.

Also keep in mind that if you pass an array or hash (or any other non-scalar object) you are passing a reference to the object **not a copy**.

Lets look at a simple (but contrived) example and see how this all plays out:

```ruby
class App < HyperComponent
  render do
    DIV do
      BUTTON { "update" }.on(:click) { force_update! }
      new_hash = {foo: {bar: [12, 13]}}
      Comp2(param: new_hash)
    end
  end
end

class Comp2 < HyperComponent
  param :param
  render do
    DIV { param }
  end
end
```

Even though we have not gotten to event handlers yet, you can see what is going on: When we click the update button we call `force_update!` which will force the `App` component to rerender.

> By the way `force_update!` is almost never used, but we are using it here just to make the example clear. Its also one of the reasons this example gets into trouble. Read on!

Will `Comp2` rerender? No - because even though we are creating a new hash, the old hash and new hash are equal in value.

What if we change the hash to be `{foo: {bar: [12, Time.now]}}`. Will `Comp2` re-render now? Yes because the old and new hashes are no longer equal.

What if we changed `App` like this:

```ruby
class App < HyperComponent
  # initialize an instance variable before rendering App
  before_mount { @hash = {foo: {bar: [12, 13]}} }
  render do
    DIV do
      BUTTON { "update" }.on(:click) do
        @hash[:foo][:bar][2] = Time.now
        force_update!
      end
      Comp2(param: @hash)
    end
  end
end
```

Will `Comp2` still update? No. `Comp2` received the value of `@hash` on the first render, and so `Comp2` is rendering the same copy of `@hash` that `App` is changing. So when we compare *old* verses *new* we are comparing the same object, so the values are equal even though the contents of the hash has changed.

## Conclusion

That does not seem like a very happy ending, but the case we used was not very realistic. If you stick to passing simple scalars, or hashes and arrays whose values don't change after they have been passed, things will work fine. And for situations where you do need to store and manipulate complex data, you can use the [**the Hyperstack::Observable module**](/hyper-state) to build safe classes that don't have the problems seen above.


# Lifecycle Methods

A component may define lifecycle methods for each phase of the components lifecycle:

* `before_mount`
* `render`
* `after_mount`
* `before_new_params`
* `before_update`
* `render` will be called again here
* `after_update`
* `before_unmount`
* `rescues` The `rescues` callback is described [**here...**](/client-dsl/error-recovery)

All the Component Lifecycle methods (except `render`) may take a block or the name(s) of instance method(s) to be called. The `render` method always takes a block.

```ruby
class MyComponent < HyperComponent
  before_mount do
    # initialize stuff here
  end

  render do
    # return some elements
  end

  before_unmount :cleanup  # call the cleanup method before unmounting
  ...
end
```

Except for `render`, multiple lifecycle callbacks may be defined for each lifecycle phase, and will be executed in the order defined, and from most deeply nested subclass outwards. Note the implication that the callbacks are inherited, which can be useful in creating [**abstract component classes**](https://github.com/hyperstack-org/hyperstack/tree/46d271dd9214d5c2a772a898e13e803bb0f25fea/docs/client-dsl/notes/README.md#abstract-and-concrete-components).

## Rendering

The lifecycle revolves around rendering the component. As the state or parameters of a component change, its render callback will be executed to generate the new HTML.

```ruby
render do 
  ...
end
```

The render method may optionally take the container component and params:

```ruby
render(DIV, class: 'my-class') do
  ...
end
```

which would be equivalent to:

```ruby
render do
  DIV(class: 'my-class') do
    ...
  end
end
```

## Before Mounting (first render)

```ruby
before_mount do 
  ...
end
```

Invoked once when the component is first instantiated, immediately before the initial rendering occurs. This is where state variables should be initialized.

This is the only life cycle callback run during `render_to_string` used in server side pre-rendering.

## After Mounting (first render)

```ruby
after_mount do 
  ...
end
```

Invoked once, only on the client (not on the server during prerendering), immediately after the initial rendering occurs. At this point in the lifecycle, you can access any refs to your children (e.g., to access the underlying DOM representation). The `after_mount` callbacks of child components are invoked before that of parent components.

If you want to integrate with other JavaScript frameworks, set timers using the `after` or `every` methods, or send AJAX requests, perform those operations in this callback. Attempting to perform such operations in before\_mount will cause errors during prerendering because none of these operations are available in the server environment.

## Before Receiving New Params

```ruby
before_new_params do |new_params_hash| 
  ...
end
```

Invoked when a component is receiving *new* params (React props). This method is not called for the initial render.

Use this as an opportunity to react to receiving new param values before `render` is called by updating any instance variables. The new\_params block parameter contains a hash of the new values.

```ruby
before_new_params do |next_params|
  @likes_increasing = (next_params[:like_count] > like_count)
end
```

> Note: There is no analogous method `before_receive_state`. An incoming param may cause a state change, but the opposite is not true. If you need to perform operations in response to a state change, use `before_update`.

## Before Updating (re-rendering)

```ruby
before_update do 
  ...
end
```

Invoked immediately before rendering when new params or state are being received.

## After Updating (re-rendering)

```ruby
after_update do 
  ...
end
```

Invoked immediately after the component's updates are flushed to the DOM. This method is not called for the initial render.

Use this as an opportunity to operate on the DOM when the component has been updated.

## Unmounting

```ruby
before_unmount do 
  ...
end
```

Invoked immediately before a component is unmounted from the DOM.

Perform any necessary cleanup in this method, such as cleaning up any DOM elements that were created in the `after_mount` method. Note that periodic timers and broadcast receivers are automatically cleaned up when the component is unmounted.

## The `before_render` and `after_render` convenience methods

These call backs occur before and after all renders (first and re-rerenders.) They provide no added functionality but allow you to keep your render methods focused on generating components.

## The force\_update! method

`force_update!` is a component instance method that causes the component to re-rerender. This method is seldom (if ever) needed.

The `force_update!` instance method causes the component to re-render. Usually this is not necessary as rendering will occur when state variables change, or new params are passed.


# Component State

When a component is rendered what it displays depends on some combination of three things:

* the value of the params passed to the component
* the state of the component
* the state of some other objects on which a component depends

Whenever one of these three things change the component will need to re-render. In this section we discuss how a component's *internal* state is managed within Hyperstack. Params were covered [**here...**](/client-dsl/params) and sharing state between components will be covered [**here...**](/hyper-state)

The idea of state is built into Ruby and is represented by the *instance* variables of an object instance.

Components very often have state. For example, is an item being displayed or edited? What is the current value of a text box? A checkbox? The time that an alarm should go off? All these are state and will be represented as values stored somewhere in instance variables.

Lets look at a simple clock component:

```ruby
class Clock < HyperComponent
  after_mount do
    every(1.second) do
      mutate @time = Time.now
    end
  end

  render(DIV) { "The time is #{@time}" }
end
```

The after\_mount call back sets up a periodic timer that goes off every second and updates the `@time` instance variable with the current time. The assignment to `@time` is wrapped in the `mutate` method which signals the React Engine that the state of `Clock` has been mutated, this in turn will add `Clock` to the list of components that need to be re-rendered.

## It's that Simple Really

To reiterate: Components (and other Ruby objects) have state, and the state + the params will determine what is rendered. When state changes we signal this using the mutate method, and any components depending on the state will be re-rendered.

## State Mutation Always Drives Rendering

It is always a mutation of state that triggers the UI to begin a render cycle. That mutation may in turn cause components to render and send different params to lower level components, but it begins with a state mutation.

## What Causes State To Mutate?

Right! Good question! State is mutated by your code's reaction to some external event. A button click, text being typed, or the arrival of data from the server. We will cover these in upcoming sections, but once an event occurs your code will probably mutate some state as a result, causing component depending on this state to update.

## Details on the `mutate` Syntax

The main purpose of `mutate` is to signal that state has changed, but it also useful to clarify how your code works. Therefore `mutate` can be used in a number of flexible ways:

* It can take any number of expressions: &#x20;

  ```ruby
  mutate @state1 = 'something', @state2 = 'something else'
  ```
* or it can take a block: &#x20;

  ```ruby
  mutate do
  ... compute the new state ...
  @state = ...
  end
  ```

In both cases the result returned by `mutate` will be the last expression executed.

## The `mutator` Class Method

This pattern:

```ruby
class SomeComponent < HyperComponent
  def update_some_state(some_args)
    ... compute new state ...
    mutate ...
  end
  ...
end
```

is common enough that Hyperstack provides two ways to shorten this code. The first is the `mutator` class method:

```ruby
  ...
  mutator :update_some_state do |some_args|
    ...compute new state ...
  end
  ...
```

In other words `mutator` defines a method that is wrapped in a call to `mutate`. It also has the advantage of clearly declaring that this method will be mutating the components state.

> Important note: If you do an early exit from the mutator using a `return` or `break` no mutation will occur. If you want to do an early exit then use the `next` keyword.

## The `state_accessor`, `state_reader` and `state_writer` Methods

Often all a mutator method will do is assign a new value to a state. For this case Hyperstack provides the `state_accessor`, `state_reader` and `state_writer` methods, that parallel Ruby's `attribute_accessor`, `attribute_reader` and `attribute_writer` methods:

```ruby
  state_accessor :some_state
  ...
  some_state = some_state + 1 # or just some_state += some_state
```

In otherwords the `state_accessor` creates methods that allow read/write access to the underlying instance variable including the call to `mutate`.

Again the advantage is not only less typing but also clarity of code and intention.

## Sharing State

You can also use and share state at the class level and create "stateful" class libraries. This is described in the [**chapter on HyperState...**](/hyper-state)

## The `force_update!` Method

We said above only state mutation can start a rerender. The `force_update!` method is the exception to this rule, as it will force a component to rerender just because you said so. If you have to use `force_update!` you may be doing something wrong, so use carefully.


# Events and Callbacks

Params pass data downwards from owner to owned-by component. Data comes back upwards asynchronously via *callbacks*, which are simply *Procs* passed as params into the owned-by component.

> [**More on Ruby Procs here ...**](/client-dsl/notes#ruby-procs)

The upwards flow of data via callbacks is triggered by some event such as a mouse click, or input change:

```ruby
class ClickDemo2 < HyperComponent
  render do
    BUTTON { "click" }.on(:click) { |evt| puts "I was clicked"}
  end
end
```

When the `BUTTON` is clicked, the event (evt) is passed to the attached click handler.

The details of the event object will be discussed below.

## Firing Events from Components

You can also define events in your components to communicate back to the owner:

```ruby
class Clicker < HyperComponent
  param title: "click"
  fires :clicked
  before_mount { @clicks = 0 }
  render do
    BUTTON { title }.on(:click) { clicked!(@clicks += 1) }
  end
end

class ClickDemo3 < HyperComponent
  render(DIV) do
    DIV { "I have been clicked #{pluralize(@clicks, 'times')}" } if @clicks
    Clicker().on(:clicked) { |clicks| mutate @clicks = clicks }
  end
end
```

Each time the `Clicker's` button is clicked it *fires* the clicked event, indicated by the event name followed by a bang (!).

The `clicked` event is received by `ClickDemo3`, and it updates its state. As you can see events can send arbitrary data back out.

> Notice also that Clicker does not call mutate. It could, but since the change in `@clicks` is not used anywhere to control its display there is no need for Clicker\
> to mutate.

## Relationship between Events and Params

Notice how events (and callbacks in general as we will see) move data upwards, while params move data downwards. We can emphasize this by updating our example:

```ruby
class ClickDemo4 < HyperComponent
  def title
    @clicks ? "Click me again!" : "Let's start clicking!"
  end

  render(DIV) do
    DIV { "I have been clicked #{pluralize(@clicks, 'times')}" } if @clicks
    Clicker(title: title).on(:clicked) { |clicks| mutate @clicks = clicks }
  end
end
```

When `ClickDemo4` is first rendered, the `title` method will return "Let's start clicking!", and will be passed to `Clicker`.

The user will (hopefully so we can get on with this chapter) click the button, which will fire the event. The handler in `ClickDemo4` will mutate its state, causing title to change to "Click me again!". The new value of the title param will be passed to `Clicker`, and `Clicker` will re-render with the new title.

**Events (and callbacks) push data up, params move data down.**

## Callbacks and Proc Params

Under the hood Events are simply params of type `Proc`, with the `on` and `fires` method using some naming conventions to clean things up:

```ruby
class IntemittentButton < HyperComponent
  param :frequency
  param :pulse, type: Proc
  before_mount { @clicks = 0 }
  render do
    BUTTON(
      on_click: lambda {} do
        @clicks += 1
        pulse(@clicks) if (@clicks % frequency).zero?
      end
    ) { 'click me' }
  end
end

class ClickDemo5 < HyperComponent
  render do
    IntermittentButton(
      frequency: 5,
      pulse: -> (total_clicks) { alert "you are clicking a lot" }
    )
  end
end
```

There is really no reason not to use the `fires` method to declare Proc params, and no reason not use the `on` method to attach handlers. Both will keep your code clean and tidy.

## Naming Conventions

The notation `on(:click)` is short for passing a proc to a param named `on_click`. In general `on(:xxx)` will pass the given block as the `on_xxx` parameter in a Hyperstack component and `onXxx` in a JS component.

All the built-in events and many React libraries follow the `on_xxx` (or `onXxx` in JS) convention. However even if a library does not use this convention you can still attach the handler using `on('<name-of-param>')`. Whatever string is inside the `<..>` brackets will be used as the param name.

Likewise the `fires` method is shorthand for creating a `Proc` param following the `on_xxx` naming convention:

`fires :foo` is short for\
`param :on_foo, type: Proc, alias: :foo!`

## The `Event` Object

UI events like `click` send an object of class `Event` to the handler. Some of the data you can get from `Event` objects are:

* `target` : the DOM object that was the target of the UI interaction
* `target.value` : the value of the DOM object
* `key_code` : the key pressed (for key\_down and key\_up events)

> [**Refer to the Predefined Events section for complete details...**](/client-dsl/predefined-events)

## Other Sources of Events

Besides the UI there are several other sources of events:

* Timers
* HTTP Requests
* Hyperstack Operations
* Websockets
* Web Workers

The way you receive events from these sources depends on the event. Typically though the method will either take a block, or callback proc, or in many cases will return a Promise. Regardless, the event handler will do one of three things: mutate some state within the component, fire an event to a higher level component, or update some shared store.

> For details on updating shared stores, which is often the best answer [**see the chapter on HyperState...**](/hyper-state)

You have seen the `every` method used to create events throughout this chapter, here is an example with an HTTP post (which returns a promise.)

```ruby
class SaveButton < HyperComponent
  fires :saved
  fires :failed
  render do
    BUTTON { "Save" }
    .on(:click) do
      # Posting to some non-hyperstack endpoint for example
      # Data is our class holding some data
      Hyperstack::HTTP.post(
        END_POINT, payload: Data.to_payload
      ).then do |response|
        saved!(response.json)
      end.fail do |response|
        failed!(response.json)
      end
    end
  end
end
```


# Interlude: Tic Tac Toe

At this point if you have been reading sequentially through these chapters you know enough to put together a simple tic-tac-toe game.

## The Game Board

The board is represented by an array of 9 cells. Cell 0 is the top left square, and cell 8 is the bottom right.

Each cell will contain nil, an `:X` or an `:O`.

## Displaying the Board

The `DisplayBoard` component displays a board. `DisplayBoard` accepts a `board` param, and will fire back a `clicked_at` event when the user clicks one of the squares.

A small helper function `draw_squares` draws an individual square which is displayed as a `BUTTON`. A click handler is attached which will fire the `clicked_at` event with the appropriate cell id.

Notice that `DisplayBoard` has no internal state of its own. That is handled by the `DisplayGame` component.

```ruby
class DisplayBoard < HyperComponent
  param :board
  fires :clicked_at

  def draw_square(id)
    BUTTON(class: :square, id: id) { board[id] }
    .on(:click) { clicked_at!(id) }
  end

  render(DIV) do
    (0..6).step(3) do |row|
      DIV(class: :board_row) do
        (row..row + 2).each { |id| draw_square(id) }
      end
    end
  end
end
```

## The Game State

The `DisplayGame` component has two state variables:

* `@history` which is an array of boards, each board being the array of cells.
* `@step` which is the current step in the history (we begin at zero)

`@step` and `@history` allows the player to move backwards or forwards and replay parts of the game.

These are initialized in the `before_mount` callback. Because Ruby will adjust the array size as needed and return nil if an array value is not initialized, we can simply initialize the board to an empty array.

There are three *reader* methods that read the state:

* `player` returns the current player's token.  The first player is always `:X` so even steps

  are `:X`, and odd steps are `:O`.
* `current` returns the board at the current step.
* `history` uses state\_reader to encapsulate the history state.

Encapsulated access to state in reader methods like this is not necessary but is good practice

```ruby
class DisplayGame < HyperComponent
  before_mount do
    @history = [[]]
    @step = 0
  end

  def player
    @step.even? ? :X : :O
  end

  def current
    @history[@step]
  end

  state_reader :history
end
```

## Calculating the Winner Based on the Game State

We also have a `current_winner?` method that will return the winning player or nil based on the value of the current board:

```ruby
class DisplayGame < HyperComponent
  WINNING_COMBOS = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ]

  def current_winner?
    WINNING_COMBOS.each do |a, b, c|
      return current[a] if current[a] && current[a] == current[b] && current[a] == current[c]
    end
    false
  end
end
```

## Mutating the Game State

There are two mutator methods that change state:

* `handle_click!` is called with the id of the square when a user clicks on a square.
* `jump_to!` moves the user back and forth through the history.

The `handle_click!` mutator first checks to make sure that no one has already won at the current step, and that no one has played in the cell that the user clicked on. If either of these conditions is true `handle_click!` returns, no mutation is signaled and nothing changes.

> If we had wanted to return AND signal a state mutation we would use the Ruby `next` keyword instead of `return`.s

To update the board `handle_click!` duplicates the squares; adds the player's token to the cell; makes a new history with the new squares on the end, and finally updates the value of `@step`.

> We like to use the convention where practical of ending mutator methods with a bang (!) so that readers of the code are aware that these will change state.

```ruby
class DisplayGame < HyperComponent
  mutator :handle_click! do |id|
    board = history[@step]
    return if current_winner? || board[id]

    board = board.dup
    board[id] = player
    @history = history[0..@step] + [board]
    @step += 1
  end

  mutator(:jump_to!) { |step| @step = step }
end
```

## The Game Display

Now we have a couple of helper methods to build parts of the game display.

* `moves` creates the list items that allow the user to move back and forth through the history.
* `status` provides the play state

```ruby
class DisplayGame < HyperComponent
  def moves
    return unless history.length > 1

    history.length.times do |move|
      LI(key: move) { move.zero? ? "Go to game start" : "Go to move ##{move}" }
        .on(:click) { jump_to!(move) }
    end
  end

  def status
    if (winner = current_winner?)
      "Winner: #{winner}"
    else
      "Next player: #{player}"
    end
  end
end
```

And finally our render method which displays the Board and the game info:

```ruby
class DisplayGame < HyperComponent
  render(DIV, class: :game) do
    DIV(class: :game_board) do
      DisplayBoard(board: current)
      .on(:clicked_at, &method(:handle_click!))
    end
    DIV(class: :game_info) do
      DIV { status }
      OL { moves }
    end
  end
end
```

> `&method` turns an instance method into a Proc rather than having to say `{ |id| handle_click(id) }`

## Summary

This small game uses everything covered in the previous sections: HTML Tags, Component Classes, Params, Events and Callbacks, and State. The project was derived from this React tutorial: <https://reactjs.org/tutorial/tutorial.html>. You may want to compare our Ruby code with the React original.

The following sections cover reference materials, and some advanced information. You may want to skip to the HyperState section which will use this example to show how state can be encapsulated, extracted and shared resulting in easier to understand and maintain code.


# Recovering from Errors

The `rescues` lifecycle callbacks run when an error is raised from within or below a component.

At the end of the rescue the component tree will be completely re-rendered from scratch. In its simplest form we need nothing but an empty block.

```ruby
class App < HyperComponent
  render(DIV) do
    H1 { "Welcome to Our App" }
    ContentWhichFailsSometimes()
  end

  rescues do
  end
end
```

When an error occurs it will be caught by the rescues block, and `App` and all lower components will be re-generated (not just re-rendered).

In most cases you may want to warn the user that something is going wrong, and also record some data about the event:

```ruby
class App < HyperComponent
  render(DIV) do
    H1 { "Welcome to Our App" }
    if @failure_fall_back
      DIV { 'Whoops we had a little problem' }
      BUTTON { 'retry' }.on(:click) { mutate @failure_fall_back = false }
    else
      ContentWhichFailsSometimes()
    end
  end

  rescues do |err|
    @failure_fall_back = true
    ReportError.run(err: err)
  end
end
```

If you don't want to involve the user, then be careful: To prevent infinite loops the React engine will not rescue failures occurring during the re-generation of the component tree. If not involving the user you may want to consider how to insure that system state is completely reset in the rescue.

The rescues method can also take explicit Error types to be rescued:

```ruby
  rescues StandardError, MyInternalError do |err|
    ...
  end
```

Like other lifecycle methods you can have multiple rescues in the same component:

```ruby
  rescues StandardError do |err|
    # code for handling StandardError
  end
  rescues MyInternalError do |err|
    # different code for handling MyInternalError
  end
```

Like Ruby's rescue keyword, errors will be caught by the innermost component with a `rescues` callback that handles that error.

The data passed to the rescue handler is an array of two items, the Ruby error that was thrown, and details generated by the React engine.

```ruby
  rescues do |e, info|
    # e is a Ruby error, and responds to backtrace, message, etc
    # info is a hash currently with the single key :componentStack
    # which is string representing the backtrace through the component
    # hierarchy
  end
```

## Caveats

1. You cannot rescue errors raised in lifecycle handlers in the same component.  Errors raised by lifecycle handlers in inner components are fine, just not in the same component as the rescue.
2. Errors raised in event handlers will neither stop the rendering cycle, nor will they be caught by a rescue callback.


# JavaScript Components

Hyperstack gives you full access to the entire universe of JavaScript libraries and components directly within your Ruby code.

Everything you can do in JavaScript is simple to do in Opal-Ruby; this includes passing parameters between Ruby and JavaScript and even passing Ruby methods as JavaScript callbacks.

> [**For more information on writing Javascript within your Ruby code...**](/client-dsl/notes#javascript)

## Importing Javascript or React Libraries

Importing and using React libraries from inside Hyperstack is very simple and very powerful. Any JavaScript or React based library can be accessible in your Ruby code.

Using Webpacker there are just a few simple steps:

* Add the library source to your project using `yarn` or `npm`
* Import the JavaScript objects you require
* Use the JavaScript or React component as if it were a Ruby class

Here is an example using the [Material UI](https://material-ui.com/) library:

Firstly, you install the library:

```
yarn add @material-ui/core
```

Next you import the objects you plan to use:

```javascript
// app/javascript/packs/client_and_server.js

// to import the whole library
Mui = require('@material-ui/core')
// or to import a single component
Button = require('@material-ui/core/Button')
```

Theoretically webpacker will detect the change and rebuild everything, but you might have to do the following:

```
bin/webpack # rebuild the webpacks
rm -rf tmp/cache # clear the cached sprockets files
```

Now you can use Material UI Components in your Ruby code:

```ruby
# if you imported the whole library
Mui::Button(variant: :contained, color: :primary) { "Click me" }.on(:click) do
  alert 'you clicked the primary button!'
end

# if you just imported the Button component
Button(variant: :contained, color: :secondary) { "Click me" }.on(:click) do
  alert 'you clicked the secondary button!'
end
```

Libraries used often with Hyperstack projects:

* [Material UI](https://material-ui.com/) Google's Material UI as React components
* [Semantic UI](https://react.semantic-ui.com/) A React wrapper for the Semantic UI stylesheet
* [ReactStrap](https://reactstrap.github.io/) Bootstrap 4 React wrapper

### Making Custom Wrappers - WORK IN PROGRESS ...

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true) Hyperstack will automatically import Javascript components and component libraries as discussed above. Sometimes for complex libraries that you will use a lot it is useful to add some syntactic sugar to the wrapper.

This can be done using the `imports` directive and the `Hyperstack::Component::NativeLibrary` superclass.

### Importing Image Assets via Webpack

If you store your images in `app/javascript/images` directory and want to display them in components, please add the following code to `app/javascript/packs/application.js`

```javascript
webpackImagesMap = {};
var imagesContext = require.context('../images/', true, /\.(gif|jpg|png|svg)$/i);

function importAll (r) {
  r.keys().forEach(key => webpackImagesMap[key] = r(key));
}

importAll(imagesContext);
```

The above code creates an images map and stores it in webpackImagesMap variable. It looks something like this

```javascript
{
     "./logo.png": "/packs/images/logo-3e11ad2e3d31a175aec7bb2f20a7e742.png",
     ...
}
```

Add the following helpers to your HyperComponent class

```ruby
# app/hyperstack/helpers/images_import.rb

class HyperComponent
  def self.img_src(file_path)  # for use outside a component
    @img_map ||= Native(`webpackImagesMap`)
    @img_map["./#{file_path}"]
  end
  def img_src(file_path) # for use in a component
    HyperComponent.img_src(file_path)
  end
  ...
end
```

After that you will be able to display the images in your components like this

```ruby
IMG(src: img_src('logo.png'))               # app/javascript/images/logo.png
IMG(src: img_src('landing/some_image.png')) # app/javascript/images/landing/some_image.png
```

## jQuery

Hyperstack comes with a jQuery wrapper that you can optionally load. First add jQuery using yarn:

```
yarn add jquery
```

then insure jQuery is required in your client\_only.js packs file:

```javascript
// app/javascript/packs/client_only.js
jQuery = require('jquery');
```

finally require it in your hyper\_component.rb file:

```ruby
# app/hyperstack/hyper_component.rb

require 'hyperstack/component/jquery'
```

You can access jQuery anywhere in your code using the `jQ` method. For details see <https://github.com/opal/opal-jquery>

> Note most of the time you will not need to manipulate the dom directly.

## The dom\_node method

Returns the HTML dom\_node that this component instance is mounted to. For example you can use `dom_node` to set the focus on an input after its mounted.

```ruby
class FocusedInput < HyperComponent
  others :others
  after_mount do
    jQ[dom_node].focus
  end
  render do
    INPUT(others)
  end
end
```


# Elements and Rendering

This section documents some technical details of the interface between React and Hyperstack as well as some useful low level methods.

## The `Hyperstack::Component` Module

The `Hyperstack::Component` module can be included in any Ruby class, and will add the methods that interface between that class and React. Specifically it will

* Define the class level methods such as param, render and the other lifecycle methods,
* Provide the render DSL which has the same role as JSX but uses Ruby methods,
* Provide a suitable Javascript class constructor that so that React will recognize the instances of the Component as React Elements

The only major difference between the systems is that JSX compiles directly to React API calls (such as `createElement`) while Hyperstack executes an expression like `MyBigComponent(class: :red, some_param: :foo)` and directly calls `createElement` passing the `MyBigComponent` react class, and translating it as needed from Ruby to JS conventions.

As each React element is generated it is stored by Hyperstack in a *rendering buffer*, and when the component finishes the rendering block, the buffer is returned as the result of the components render callback. If the expression has a child block (like `DIV { 'hello' }`) the block is passed to the `createElement` as a the child function the same as JSX would do.

When an expression like this is evaluated ([**see the full example in the section on params...**](/client-dsl/params#named-child-components-as-params))

```ruby
  Reveal(content: DIV { 'I came from the App' })
```

we need to *remove* the generated `DIV` element *out* of the rendering buffer before passing it to `Reveal`. This is done automatically by applying the `~` (remove) operator to the `DIV` as it is passed on.

In general you will never have to manually use the remove (`~`) operator, as React's declarative nature makes storing elements for later use not as necessary as in more procedural frameworks.

#### Creating Elements Programmatically

Component classes (including tags like `DIV`) respond to two methods for programmatically creating elements:

```ruby
# component_class evaluates to some Component Class
component_class.create_element(<params hash>) { <optional block> }
component_class.insert_element(<params hash>) { <optional block> }
```

both methods return the generated element, the second also inserts into the current rendering buffer.

#### Rendering to the DOM

Sooner or later it has to end up in the DOM. If you are using Rails then Hyperstack includes several methods to *mount* your components onto the display. See the Rails installation section for details.

Otherwise if using jQuery then you can use the `render` method:

```ruby
Document.ready? do # ready runs when document is loaded
  jQ['div#mount_point'].render(App)
end
```

or do it completely yourself with the low level ReactAPI

```ruby
# somewhere in a JS onload page handler:
Hyperstack::Component::ReactAPI.render(App.create_element, `getElementById('mount_point')`)
```

#### React.unmount\_component\_at\_node

To remove a element that has been mounted:

```ruby
Hyperstack::Component::ReactAPI.unmount_component_at_node(dom_container)
```

This removes a mounted component from the DOM and cleans up its event handlers and state. If no component was mounted in the container, calling this function does nothing. Returns `true` if a component was unmounted and `false` if there was no component to unmount.

### React.render\_to\_string

```ruby
Hyperstack::Component::ReactAPI.render_to_string(element)
```

Render an element to its initial HTML. This is should only be used on the server for prerendering content. React will return a string containing the HTML. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.

If you call `ReactAPI.render` on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.

If you are using rails, then the prerendering functions are automatically performed. Otherwise you can use `render_to_string` to build your own prerendering system.

### React.render\_to\_static\_markup

```ruby
React.render_to_static_markup(element)
```

Similar to `render_to_string`, except this doesn't create extra DOM attributes such as `data-react-id`, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes.

### HTML Entities

If you want to display an HTML entity within dynamic content, you will run into double escaping issues as React.js escapes all the strings you are displaying in order to prevent a wide range of XSS attacks by default.

```ruby
DIV {'First &middot; Second' }
  # Bad: It displays "First &middot; Second"
```

To workaround this you have to insert raw HTML.

```ruby
DIV(dangerously_set_inner_HTML: { __html: "First &middot; Second"})
```

### Custom HTML Attributes

If you pass properties to native HTML elements that do not exist in the HTML specification, React will not render them. If you want to use a custom attribute, you should prefix it with `data-`.

```ruby
DIV("data-custom-attribute" => "foo")
```

[Web Accessibility](http://www.w3.org/WAI/intro/aria) attributes starting with `aria-` will be rendered properly.

```ruby
DIV("aria-hidden" => true)
```


# Summary of Methods

## Class Methods

The following methods are used to define the interface and behavior of instances of the component class. You may also use any other Ruby constructs such as method definition as you would in any Ruby class.

**Interface Definition** These methods define the signature of the component's params.

* `param(*args)` - specifies params and creates accessor methods
* `fires(name, alias: internal_name)` - specifies an event call-back
* `others(name)` accessor method that collects all params not otherwise specified
* `other, other_params, opts, collect_other_params_as` aliases for `others`

**Lifecycle Methods** These methods define the behavior of the component through its lifecycle. All components must have a `render` callback. If no signature is specified the method will take a list of method names, and/or a callback block. Except for render, you may define multiple handlers for each callback.

* `render(opt_comp_name, opt_params, &block)`
* `before_mount`
* `after_mount`
* `before_new_params`
* `before_update`
* `after_update`
* `before_render` before all renders
* `after_render` after all renders
* `rescues(*klasses_to_rescue, &block)`

**State Management** Each component instance has internal state represented by the contents of instance variables: changes to the state is signaled using the `mutate` method. The following methods define additional instance methods that access state with built-in calls to the mutate method.

* `mutator` defines an *instance* method with a built-in mutate.
* `state_reader` creates an *instance* state read only accessor method.
* `state_writer` creates an *instance* state write only accessor method.
* `state_accessor` creates *instance* reader and writer methods.

**Other Class Level Methods**

* `mounted_components` - returns an array of all currently mounted components of this class and subclasses
* `force_update!` forces all components in this class and its subclasses to update
* `create_element(*params, &children)` - create an element from this class
* `insert_element(*params, &children)` - create and insert an element into the rendering buffer

## Instance Methods

**Inserting Elements**

All HTML and SVG tags, and all other Components visible to this instance can be inserted into the rendering buffer by using the tag or component class name followed either by parens and/or a block:

`DIV(...)` or `DIV { ... }` or `DIV(...) { ... }`

Note that this is just short for `DIV.insert_element(...) { ... }`

Parameters can be passed as a combination of strings and symbols followed by any number of hashes.

Any symbols or strings will be treated as a hash key with a value of true and will be merged with the rest of the hashes:

```ruby
MyComp(:foo, 'bar-ski', {class: :joe, id: 12}, data: 123)
# is the same as
MyComp(foo: true, 'bar-ski' => true, class: :joe, id: 12, data: 123)
```

**Attaching Callback Handlers**

Component params that expect `Procs` can passed as normal or using the `.on` method:

```ruby
BUTTON { 'click me' }.on(:click) { alert('you clicked?') }
# is the same as
BUTTON(on_click: -> { alert('you clicked') }) { 'click me' }
```

**State Management**

When an event occurs it will probably change state. The mutate method is used to signal the state change.

* `mutate` signals that this instance's state has been mutated
* `toggle(:foo)` is short for `mutate @foo = !@foo`

**Other Methods**

* `children` enumerates the children of this component
* `alert(message)` js alert
* `after(time, &block)` run block after `time` seconds
* `every(time, &block)` run block every `time` seconds
* `pluralize(count, singular, plural = nil)` equivalent to Rails pluralize helper
* `dom_node` returns the DOM node of this component
* `jq_node` short for `jQ[dom_node]`
* `force_update!` Almost always components should render due to a state change or when receiving new params.
* `~` Removes the instance from the current rendering buffer.  This is done automatically in most cases when needed.


# List of Predefined Tags & Components

## HTML Tags

```
A ABBR ADDRESS AREA ARTICLE ASIDE AUDIO  
B BASE BDI BDO BIG BLOCKQUOTE BODY BR BUTTON  
CANVAS CAPTION CITE CODE COL COLGROUP  
DATA DATALIST DD DEL DETAILS DFN DIALOG DIV DL DT  
EM EMBED  
FIELDSET FIGCAPTION FIGURE FOOTER FORM  
H1 H2 H3 H4 H5 H6 HEAD HEADER HR HTML  
I IFRAME IMG INPUT INS  
KBD KEYGEN  
LABEL LEGEND LI LINK  
MAIN MAP MARK MENU MENUITEM META METER  
NAV NOSCRIPT  
OBJECT OL OPTGROUP OPTION OUTPUT  
P PARAM PICTURE PRE PROGRESS  
Q  
RP RT RUBY  
S SAMP SCRIPT SECTION SELECT SMALL SOURCE SPAN STRONG STYLE SUB SUMMARY SUP  
TABLE TBODY TD TEXTAREA TFOOT TH THEAD TIME TITLE TR TRACK  
U UL  
VAR VIDEO  
WBR
```

## SVG Tags

```
CIRCLE CLIPPATH  
DEFS  
ELLIPSE  
G  
LINE LINEARGRADIENT  
MASK  
PATH PATTERN POLYGON POLYLINE  
RADIALGRADIENT RECT  
STOP  
SVG  
TEXT TSPAN
```

## The FRAGMENT Tag

The `FRAGMENT` tag is used to return multiple *static* children from a component or block. The only valid param to `FRAGMENT` is `key`. See the [**React documentation**](https://reactjs.org/docs/fragments.html) for more details. If a render block returns dynamic children that will change in number and order, each child should be assigned a unique key, and the FRAGMENT tag does not have to be used.


# Predefined Events

Event Handlers are attached to tags and components using the `on` method.

```ruby
SELECT ... do
  ...
end.on(:change) do |e|
  mutate @mode = e.target.value.to_i
end
```

The `on` method takes the event name symbol (note that `onClick` becomes `:click`) and the block is passed the React.js event object.

```ruby
BUTTON { 'Press me' }.on(:click) { do_something }
# you can add an event handler to any HTML element
H1(class: :cursor_hand) { 'Click me' }.on(:click) { do_something }
```

Event handlers can be chained like so

```ruby
  INPUT ... do
  ...
  end.on(:key_up) do |e|
  ...
  end.on(:change) do |e|
  ...
  end
```

## Event Handling and Synthetic Events

The React engine ensures that all events behave identically in IE8 and above by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.

## Under the Hood: Event Delegation

React doesn't actually attach event handlers to the nodes themselves. When React starts up, it starts listening for all events at the top level using a single event listener. When a component is mounted or unmounted, the event handlers are simply added or removed from an internal mapping. When an event occurs, React knows how to dispatch it using this mapping. When there are no event handlers left in the mapping, React's event handlers are simple no-ops. To learn more about why this is fast, see [**David Walsh's excellent blog post ...**](http://davidwalsh.name/event-delegate)**.**

## React::Event

Your event handlers will be passed instances of `Hyperstack::Component::Event`, a wrapper around react.js's `SyntheticEvent` which in turn is a cross browser wrapper around the browser's native event. It has the same interface as the browser's native event, including `stop_propagation()` and `prevent_default()`, except the events work identically across all browsers.

For example:

```ruby
class YouSaid < HyperComponent
  state_accessor :value
  render(DIV) do
    INPUT(value: value)
    .on(:key_down) do |e|
      next unless e.key_code == 13

      alert "You said: #{value}"
      self.value = ""
    end
    .on(:change) do |e|
      self.value = e.target.value
    end
  end
end
```

> Hyperstack also includes an `enter` event that fires on key\_down **when** the key\_code == 13. [**See that version here ...**](/client-dsl/notes#the-enter-event)

If you find that you need the underlying browser event for some reason use the `native_event` method (i.e. `evt.native_event`).

In the following responses shown as (native ...) indicate the value returned is a native object with an Opal wrapper. In some cases there will be opal methods available (i.e. for native DOMNode values) and in other cases you will have to convert to the native value with `.to_n` and then use javascript directly.

Every `Event` has the following methods:

```ruby
bubbles                -> Boolean
cancelable             -> Boolean
current_target         -> (native DOM node)
default_prevented      -> Boolean
event_phase            -> Integer
is_trusted             -> Boolean
native_event           -> (native Event)
prevent_default        -> Proc
is_default_prevented   -> Boolean
stop_propagation       -> Proc
is_propagation_stopped -> Boolean
target                 -> (native DOMEventTarget)
timestamp              -> Integer (use Time.at to convert to Time)
type                   -> String
```

## Event pooling

The underlying React `SyntheticEvent` is pooled. This means that the `SyntheticEvent` object will be reused and all properties will be nullified after the event method has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way - don't store the whole event and think you can use it later after you ate breakfast.

## Clipboard Events

Event names:

```ruby
:copy, :cut, :paste
```

Available Methods:

```ruby
clipboard_data -> (native DOMDataTransfer)
```

## Composition Events (not tested)

Event names:

```ruby
:composition_end, :composition_start, :composition_update
```

Available Methods:

```ruby
data -> String
```

## Keyboard Events

Event names:

```ruby
:key_down, :key_press, :key_up, :enter
```

> The `enter` event is fired on key\_down where key\_code == 13 (the enter key)

Available Methods:

```ruby
alt_key                 -> Boolean
char_code               -> Integer
ctrl_key                -> Boolean
get_modifier_state(key) -> Boolean (i.e. get_modifier_key(:Shift)
key                     -> String
key_code                -> Integer
locale                  -> String
location                -> Integer
meta_key                -> Boolean
repeat                  -> Boolean
shift_key               -> Boolean
which                   -> Integer
```

## Focus Events

Event names:

```ruby
:focus, :blur
```

Available Methods:

```ruby
related_target -> (Native DOMEventTarget)
```

These focus events work on all elements in the React DOM, not just form elements.

## Form Events

Event names:

```ruby
:change, :input, :submit
```

## Mouse Events

Event names:

```ruby
:click, :context_menu, :double_click, :drag, :drag_end, :drag_enter, :drag_exit
:drag_leave, :drag_over, :drag_start, :drop, :mouse_down, :mouse_enter,
:mouse_leave, :mouse_move, :mouse_out, :mouse_over, :mouse_up
```

The `:mouse_enter` and `:mouse_leave` events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.

Available Methods:

```ruby
alt_key                 -> Boolean
button                  -> Integer
buttons                 -> Integer
client_x                -> Integer
number client_y         -> Integer
ctrl_key                -> Boolean
get_modifier_state(key) -> Boolean
meta_key                -> Boolean
page_x                  -> Integer
page_y                  -> Integer
related_target          -> (Native DOMEventTarget)
screen_x                -> Integer
screen_y                -> Integer
shift_key               -> Boolean
```

## Drag and Drop example

Here is a Hyperstack version of this [**w3schools.com**](https://www.w3schools.com/html/html5_draganddrop.asp) example:

```ruby
DIV(id: :div1, style: { width: 350, height: 70, padding: 10, border: '1px solid #aaaaaa' })
.on(:drop) do |evt|
  evt.prevent_default
  data = `#{evt.native_event}.native.dataTransfer.getData("text")`
  `#{evt.target}.native.appendChild(document.getElementById(data))`
end
.on(:drag_over, &:prevent_default)

IMG(id: :drag1, src: "https://www.w3schools.com/html/img_logo.gif", draggable: "true", width: 336, height: 69)
.on(:drag_start) do |evt|
  `#{evt.native_event}.native.dataTransfer.setData("text", #{evt.target}.native.id)`
end
```

## Selection events

Event names:

```ruby
onSelect
```

## Touch events

Event names:

```ruby
:touch_cancel, :touch_end, :touch_move, :touch_start
```

Available Methods:

```ruby
alt_key                 -> Boolean
changed_touches         -> (Native DOMTouchList)
ctrl_key                -> Boolean
get_modifier_state(key) -> Boolean
meta_key                -> Boolean
shift_key               -> Boolean
target_touches          -> (Native DOMTouchList)
touches                 -> (Native DomTouchList)
```

## UI Events

Event names:

```ruby
:scroll
```

Available Methods:

```ruby
detail -> Integer
view   -> (Native DOMAbstractView)
```

## Wheel Events

Event names:

```ruby
wheel
```

Available Methods:

```ruby
delta_mode -> Integer
delta_x    -> Integer
delta_y    -> Integer
delta_z    -> Integer
```

## Media Events

Event names:

```ruby
:abort, :can_play, :can_play_through, :duration_change,:emptied, :encrypted, :ended, :error, :loaded_data,
:loaded_metadata, :load_start, :pause, :play, :playing, :progress, :rate_change, :seeked, :seeking, :stalled,
:on_suspend, :time_update, :volume_change, :waiting
```

## Image Events

Event names:

```ruby
:load, :error
```


# Notes

## Blocks in Ruby

Ruby methods may *receive* a block which is simply an anonymous function.

The following code in Ruby:

```ruby
some_method(1, 2, 3) { |x| puts x }
```

is roughly equivilent to this Javascript

```javascript
some_method(1, 2, 3 function(x) { console.log(x) })
```

In Ruby blocks may be specified either using `do ... end` or with `{ ... }`:

```ruby
some_method { an_expression }
# or
some_method do
  several
  expressions
end
```

Standard style reserves the `{ ... }` notation for single line blocks, and `do ... end` for multiple line blocks.

## Component Instances

Currently when generating a component the actual value returned after processing by React is an instance of class `Element`. The long term plan is to merge these two concepts back together so that Element instances and Component instances will be the same. The major difference at the moment is that an Element carries all the data needed to create a Component Instance, but has not yet been rendered. Through out this document we will use element and component instance interchangeably.

## Ruby Hash Params

In Ruby if the final argument to a method is a hash you may leave the `{...}` off:

```ruby
some_method(1, 2, {a: 2, b: 3}) # same as
some_method(1, 2, a: 2, b: 3)
```

## The HyperComponent Base Class

By convention all your components inherit from the `HyperComponent` base class, which would typically look like this:

```ruby
# components/hyper_component.rb
class HyperComponent
  # All component classes must include Hyperstack::Component
  include Hyperstack::Component
  # The Observable module adds state handling
  include Hyperstack::State::Observable
  # The following turns on the new style param accessor
  # i.e. param :foo is accessed by the foo method
  param_accessor_style :accessors
end
```

> The Hyperstack Rails installer and generators will create this class for you if it does not exist, or you may copy the above to your `components` directory.

Having an application wide `HyperComponent` class allows you to modify component behavior on an application basis, similar to the way Rails uses `ApplicationRecord` and `ApplicationController` classes.

> This is just a convention. Any class that includes the `Hyperstack::Component` module can be used as a Component. You also do not have to name it `HyperComponent`. For example some teams prefer `ApplicationComponent` more closely following the Rails convention. If you use a different name for this class be sure to set the `Hyperstack.component_base_class` setting so the Rails generators will use the proper name when generating your components. [**more details...**](/rails-installation/generators#specifying-the-base-class)

## Abstract and Concrete Components

An *abstract* component class is intended to be the base class of other components, and thus does not have a render block. A class that defines a render block is a concrete class. The distinction between *abstract* and *concrete* is useful to distinguish classes like `HyperComponent` that are intended to be subclassed.

Abstract classes are often used to share common code between subclasses.

## Word Count Method

```ruby
def word_count(text)
  text.downcase                      # all lower case
      .gsub(/\W/, ' ')               # get rid of special chars
      .split(' ')                    # divide into an array of words
      .group_by(&:itself)            # group into arrays of the same words
      .map{|k, v| [k, v.length]}     # convert to [word, # of words]
      .sort { |a, b| b[1] <=> a[1] } # sort descending (that was fun!)
end
```

## Ownership

In the Avatar example instances of `Avatar` *own* instances of `ProfilePic` and `ProfileLink`. In Hyperstack (like React), **an owner is the component that sets the `params` of other components**. More formally, if a component `X` is created in component `Y`'s `render` method, it is said that `X` is *owned by* `Y`. As will be discussed later a component cannot mutate its `params` — they are always consistent with what its owner sets them to. This fundamental invariant leads to UIs that are guaranteed to be consistent.

It's important to draw a distinction between the owner-owned-by relationship and the parent-child relationship. The owner-owned-by relationship is specific to Hyperstack/React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `DIV`, `ProfilePic` and `ProfileLink` instances, and `DIV` is the **parent** (but not owner) of the `ProfilePic` and `ProfileLink` instances.

```ruby
class Avatar < HyperComponent
  param :user_name

  render do # this can be shortened to render(DIV) do - see the previous section
    DIV do
      ProfilePic(user_name: user_name)  # belongs to Avatar, owned by DIV
      ProfileLink(user_name: user_name) # belongs to Avatar, owned by DIV
    end
  end
end

class ProfilePic < HyperComponent
  param :user_name
  render { IMG(src: "https://graph.facebook.com/#{user_name}/picture") }
end

class ProfileLink < HyperComponent
  param :user_name
  render do
    A(href: "https://www.facebook.com/#{user_name}") do
      user_name
    end
  end
end
```

## Generating Keys

Every Hyperstack object whether its a string, integer, or some complex class responds to the `to_key` method. When you provide a component's key parameter with any object, the object's `to_key` method will be called, and return a unique key appropriate to that object.

For example strings, and numbers return themselves. Other complex objects return the internal `object_id`, and some classes provide their own `to_key` method that returns some invariant value for each instance of that class. HyperModel records return the database id for example.

If you are creating your own data classes keep this in mind. You simply define a `to_key` method on the class that returns some value that will be unique to that instance. And don't worry if you don't define a method, it will default to the one provided by Hyperstack.

## Proper Use Of Keys

For best results the `key` is supplied at highest level possible.

> NOTE THIS MAY NO LONGER BE AN ISSUE IN LATEST REACT)

```ruby
# WRONG!
class ListItemWrapper < HyperComponent
  param :data
  render do
    LI(key: data[:id]) { data[:text] }
  end
end  

class MyComponent < HyperComponent
  param :results
  render do
    UL do
      result.each do |result|
        ListItemWrapper data: result
      end
    end
  end
end
```

```ruby
# CORRECT
class ListItemWrapper < HyperComponent
  param :data
  render do
    LI { data[:text] }
  end
end

class MyComponent < HyperComponent
  param :results
  render do
    UL do
      results.each do |result|
        ListItemWrapper key: result[:id], data: result
      end
    end
  end
end
```

## Ruby Procs

A core class of objects in Ruby is the *Proc*. A Proc (Procedure) is an object that can be *called*.

```ruby
some_proc.call(1, 2, 3)
```

Ruby has several ways to create procs:

```ruby
# create a proc that will add its three parameters together
# using Proc.new
some_proc = Proc.new { |a, b, c| a + b + c }
# using the lambda method:
some_proc = lambda { |a, b, c| a + b + c }
# or the hash rocket notation:
some_proc = -> (a, b, c) { a + b + c }
# using a method (assuming self responds to foo)
some_proc = method(:foo)
```

And there are several more ways, each with its differences and uses. You can find lots of details on Procs by searching online. [**Here is a good article to get you started...**](https://blog.appsignal.com/2018/09/04/ruby-magic-closures-in-ruby-blocks-procs-and-lambdas.html)

The most common ways you will use Procs in your Hyperstack code is to define either lifecycle or component callbacks:

```ruby
class Foo < HyperComponent
  before_mount :do_it_before
  after_mount { puts "I did it after" }
  render do
    BUTTON(on_click: ->() { puts "clicked Using a lambda" } ) { "click me" }
    BUTTON { "no click me" }.on(:click) { puts "clicked using the on method" }
  end
  def do_it_before
    puts "I did it before"
  end
end
```

The different ways of specifying callbacks allow you to keep your code clear and consise, but in the end they do the same thing.

> Note that there are subtle differences between Proc.new and lambda, that are beyond the scope of this note.

## Javascript

Opal-Ruby uses the backticks and `%x{ ... }` to drop blocks of Javascript code directly into your Ruby code.

```ruby
def my_own_console(message)
  # crab-claws can be used to escape back out to Ruby
  `console.log(#{message})`
end
```

Both the backticks and `%x{ ... }` work the same, but the `%{ ... }` notation is useful for multiple lines of code.

## How Importing Works

Hyperstack automates as much of the process as possible for bridging between React and Javascript, however you do have lower level control as needed.

Let's say you have an existing React Component written in Javascript that you would like to access from Hyperstack.

Here is a simple hello world component:

```javascript
window.SayHello = class extends React.Component {
  constructor(props) {
    super(props);
    this.displayName = "SayHello"
  }
  render() { return React.createElement("div", null, "Hello ", this.props.name); }
}
```

> I'm sorry I can't resist. Really?
>
> ```ruby
> class SayHello < HyperComponent
>   param :name
>   render(DIV) { "Hello #{name}"}
> end
> ```
>
> In what world is the Ruby not much better than that JS hot mess.

Assuming that this component is loaded some place in your assets, you can then access this from Hyperstack by creating a wrapper Component:

```ruby
class SayHello < HyperComponent
  imports 'SayHello'
end

class MyBigApp < HyperComponent
  render(DIV) do
    # SayHello will now act like any other Hyperstack component
    SayHello name: 'Matz'
  end
end
```

The `imports` directive takes a string (or a symbol) and will simply evaluate it and check to make sure that the value looks like a React component, and then set the underlying native component to point to the imported component.

Normally you do not have to use `imports` explicitly. When Hyperstack finds a component named in your code that is undefined it searches for a Javascript class whose matches, and which acts like a React component class. Once find it creates the class and imports for you.

You may also turn off the autoimport function if necessary in your `hyperstack.rb` initializer:

```ruby
# do not use the auto-import module
Hyperstack.cancel_import    'hyperstack/component/auto-import'
```

## The Enter Event

The :enter event is short for catching :key\_down and then checking for a key code of 13.

```ruby
class YouSaid < HyperComponent
  state_accessor :value
  render(DIV) do
    INPUT(value: value)
    .on(:enter) do
      alert "You said: #{value}"
      self.value = ""
    end
    .on(:change) do |e|
      self.value = e.target.value
    end
  end
end
```


# Further Reading

## React

To master Hyperstack you do need a solid understanding of the underlying philosophy of React and its component based architecture. The 'Thinking in React' tutorial below is an excellent place to start. Most searches for help on Google will take you to examples written in JSX or ES6 JavaScript but you will learn over time to translate this to Hyperstack easily.

* [Thinking in React](https://facebook.github.io/react/docs/thinking-in-react.html)
* [React](https://facebook.github.io/react/docs/getting-started.html)
* [React Router](https://github.com/reactjs/react-router)

## Opal

Hyperstack uses Opal to generate JavaScript from Ruby code. It is well worth reading the Opal guides and the Opal JQuery docs.

* [Opal](https://opalrb.com/)
* [Opal JQuery Docs](https://www.rubydoc.info/github/opal/opal-jquery/Element)
* [Awesome Opal](https://github.com/fazibear/awesome-opal)


# HyperState

## Revisiting the Tic Tac Toe Game

The easiest way to understand HyperState is by example. If you you did not see the Tic-Tac-Toe example, then [**please review it now**](https://github.com/hyperstack-org/hyperstack/tree/9a6e46682720cd7359feb3e6bed1c9953a5ba945/client-dsl/interlude-tic-tac-toe.md), as we are going to use this to demonstrate how to use the `Hyperstack::State::Observable` module.

In our original Tic-Tac-Toe implementation the state of the game was stored in the `DisplayGame` component. State was updated by "bubbling up" events from lower level components up to `DisplayGame` where the event handler updated the state.

This is a nice simple approach but suffers from two issues:

* Each level of lower level components must be responsible for bubbling up the events to the higher component.
* The `DisplayGame` component is responsible for both managing state and displaying the game.

As our applications become larger we will want a way to keep each component's interface isolated and not dependent on the overall architecture, and to insure good separation of concerns.

The `Hyperstack::State::Observable` module allows us to put the game's state into a separate class which can be accessed from any component: No more need to bubble up events, and no more cluttering up our `DisplayGame` component with state management and details of the game's data structure.

Here is the game state and associated methods moved out of the `DisplayGame` component into its own class:

```ruby
class Game
  include Hyperstack::State::Observable

  def initialize
    @history = [[]]
    @step = 0
  end

  observer :player do
    @step.even? ? :X : :O
  end

  observer :current do
    @history[@step]
  end

  state_reader :history

  WINNING_COMBOS = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]

  def current_winner?
    WINNING_COMBOS.each do |a, b, c|
      return current[a] if current[a] && current[a] == current[b] && current[a] == current[c]
    end
    false
  end

  mutator :handle_click! do |id|
    board = history[@step]
    return if current_winner? || board[id]

    board = board.dup
    board[id] = player
    @history = history[0..@step] + [board]
    @step += 1
  end

  mutator(:jump_to!) { |step| @step = step }
end
```

Let's go over the each of the differences from the code that was in the `DisplayGame` component.

```ruby
class Game
  include Hyperstack::State::Observable
```

`Game` is now in its own class and includes `Hyperstack::State::Observable`. This adds a number of methods to `Game` that allows our class to become a *reactive store*. When `Game` interacts with other stores and components they will be updated as the state of `Game` changes.

```ruby
  def initialize
    @history = [[]]
    @step = 0
  end
```

In the original implementation we initialized the two state variables `@history` and `@step` in the `before_mount` callback. The same initialization is now in the `initialize` method which will be called when a new instance of the game is created. This will still be done in the `DisplayGame` `before_mount` callback (see below.)

```ruby
  observer :player do
    @step.even? ? :X : :O
  end

  observer :current do
    @history[@step]
  end
```

In the original implementation we had instance methods `player` and `current`. Now that `Game` is a separate class we define these methods using `observer`.

The `observer` method creates a method that is the inverse of `mutator`. While `mutate` (and `mutator`) indicate that state has been changed `observe` and `observer` indicate that state has been accessed outside the class.

```ruby
  attr_reader :history
```

Just as we have `mutate`, `mutator`, and `state_writer`, we have `observe`, `observer`, and `state_reader`.

```ruby
  WINNING_COMBOS = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]

  def current_winner?
    WINNING_COMBOS.each do |a, b, c|
      return current[a] if current[a] && current[a] == current[b] && current[a] == current[c]
    end
    false
  end
```

We don't need any changes to `current_winner?`. It accesses the internal state through the `current` method so there is no need to explicitly make `current_winner?` an observer (but we could, without affecting anything.)

```ruby
  mutator :handle_click! do |id|
    board = history[@step]
    return if current_winner? || board[id]

    board = board.dup
    board[id] = player
    @history = history[0..@step] + [board]
    @step += 1
  end

  mutator(:jump_to!) { |step| @step = step }
end
```

Finally we need no changes to the `handle_click!` and `jump_to!` mutators either.

### The Updated DisplayGame Component

```ruby
class DisplayGame < HyperComponent
  before_mount { @game = Game.new }
  def moves
    return unless @game.history.length > 1

    @game.history.length.times do |move|
      LI(key: move) { move.zero? ? "Go to game start" : "Go to move ##{move}" }
        .on(:click) { @game.jump_to!(move) }
    end
  end

  def status
    if (winner = @game.current_winner?)
      "Winner: #{winner}"
    else
      "Next player: #{@game.player}"
    end
  end

  render(DIV, class: :game) do
    DIV(class: :game_board) do
      DisplayCurrentBoard(game: @game)
    end
    DIV(class: :game_info) do
      DIV { status }
      OL { moves }
    end
  end
end
```

The `DisplayGame` `before_mount` callback is still responsible for initializing the game, but it no longer needs to be aware of the internals of the game's state. It simply calls `Game.new` and stores the result in the `@game` instance variable. For the rest of the component's code we call the appropriate method on `@game`.

We will need to pass the entire game to `DisplayBoard` (we will see why shortly) so we will rename it to `DisplayCurrentBoard`.

As we will see `DisplayCurrentBoard` will be responsible for directly notifying the game that a user has clicked, so we do not need to handle any events coming back from `DisplayCurrentBoard`.

### The DisplayCurrentBoard Component

```ruby
class DisplayCurrentBoard < HyperComponent
  param :game

  def draw_square(id)
    BUTTON(class: :square, id: id) { game.current[id] }
    .on(:click) { game.handle_click!(id) }
  end

  render(DIV) do
    (0..6).step(3) do |row|
      DIV(class: :board_row) do
        (row..row + 2).each { |id| draw_square(id) }
      end
    end
  end
end
```

The `DisplayCurrentBoard` component receives the entire game, and it will access the current board, using the `current` method, and will directly notify the game when a user clicks using the `handle_click!` method.

By having `DisplayCurrentBoard` directly deal with user actions, we simplify both components as they do not have to communicate back upwards via events. Instead we communicate through the central game store.

## The Flux Loop

Rather than sending params down to lower level components, and having the components bubble up events, we have created a *Flux Loop*. The `Game` store holds the state, the top level component reads the state and sends it down to lower level components, those components update the `Game` state causing the top level component to re-rerender.

This structure greatly simplifies the structure and understanding of our components, and keeps each component functionally isolated.

Furthermore algorithms such as `current_winner?` now are neatly abstracted out into their own class.

## Classes and Instances

If we are sure we will only want one game board, we could define `Game` with class methods like this:

```ruby
class Game
  include Hyperstack::State::Observable

  class << self
    def initialize
      @history = [[]]
      @step = 0
    end

    observer :player do
      @step.even? ? :X : :O
    end

    observer :current do
      @history[@step]
    end

    state_reader :history

    WINNING_COMBOS = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]

    def current_winner?
      WINNING_COMBOS.each do |a, b, c|
        return current[a] if current[a] && current[a] == current[b] && current[a] == current[c]
      end
      false
    end

    mutator :handle_click! do |id|
      board = history[@step]
      return if current_winner? || board[id]

      board = board.dup
      board[id] = player
      @history = history[0..@step] + [board]
      @step += 1
    end

    mutator(:jump_to!) { |step| @step = step }
  end
end

class DisplayBoard < HyperComponent
  param :board

  def draw_square(id)
    BUTTON(class: :square, id: id) { board[id] }
    .on(:click) { Game.handle_click!(id) }
  end

  render(DIV) do
    (0..6).step(3) do |row|
      DIV(class: :board_row) do
        (row..row + 2).each { |id| draw_square(id) }
      end
    end
  end
end

class DisplayGame < HyperComponent
  def moves
    return unless Game.history.length > 1

    Game.history.length.times do |move|
      LI(key: move) { move.zero? ? "Go to game start" : "Go to move ##{move}" }
        .on(:click) { Game.jump_to!(move) }
    end
  end

  def status
    if (winner = Game.current_winner?)
      "Winner: #{winner}"
    else
      "Next player: #{Game.player}"
    end
  end

  render(DIV, class: :game) do
    DIV(class: :game_board) do
      DisplayBoard(board: Game.current)
    end
    DIV(class: :game_info) do
      DIV { status }
      OL { moves }
    end
  end
end
```

Now instead of creating an instance and passing it around we call the class level methods on `Game` throughout.

The `Hyperstack::State::Observable` module will call any class level `initialize` methods in the class or subclasses before the first component mounts.

Note that with this approach we can go back to passing just the current board to `DisplayBoard` as `DisplayBoard` can directly access `Game.handle_click!` since there is only one game.

## Thinking About Stores

To summarize: a store is simply a Ruby object or class that using the `observe` and `mutate` methods marks when its internal data has been observed by some other class, or when its internal data has changed.

When components render they observe stores throughout the system, and when those stores mutate the components will rerender.

You as the programmer need only to remember that public methods that read *internal* state must at some point during their execution declare this using `observe`, `observer`, `state_reader` or `state_accessor` methods. Likewise a method that changes *internal* state must declare this using `mutate`, `mutator`, `state_writer` or `state_accessor` methods.

If your store's methods access other stores, you do not need worry about their state, only your own. On the other hand keep in mind that the built in Ruby Array and Hash classes are **not** stores, so when you modify or read an Array or a Hash its up to you to use the appropriate `mutate` or `observe` method.

## Stores and Parameters

Typically in a large system you will have one or more central stores, and what you end up passing as parameters are either instances of those stores, or some other kind of index into the store. If there is only one store (as in the case of our Game), you need not pass any parameters at all.

We can rewrite the previous iteration of `DisplayBoard` to demonstrate this:

```ruby
class DisplaySquare
  param :id
  render
    BUTTON(class: :square, id: id) { Game.current[id] }
    .on(:click) { Game.handle_click(id) }
  end
end

class DisplayBoard < HyperComponent
  render(DIV) do
    (0..6).step(3) do |row|
      DIV(class: :board_row) do
        (row..row + 2).each { |id| DisplaySquare(id: id) }
      end
    end
  end
end
```

Here `DisplayBoard` no longer takes any parameter (and could be renamed again to `DisplayCurrentBoard`) and now a new component - `DisplaySquare` - takes the id of the square to display, but the game or the current board are never passed as parameters; there is no need to as they are implicit.

Whether to pass (or not pass) a store class, an instance of a store, or some other index into the store is a design decision that depends on lots of factors, mainly how you see your application evolving over time.

## Summary of Methods

All the observable methods can be used either at the class or instance level.

### Observing State: `observe, observer, state_reader`

The `observe` method takes any number of arguments and/or a block. The last argument evaluated or the value of the block is returned.

The arguments and block are evaluated then the object's state will be *observed*.

If the block exits with a return or break, the state will **not** be observed.

```ruby
# evaluate and return a value
observe @history[@step]

# evaluate a block and return its value
observe do
  @history[@step]
end
```

The `observer` method defines a new method with an implicit observe:

```ruby
observer :foo do |x, y, z|
  ...
end
```

is equivilent to

```ruby
def foo(x, y, z)
  observe do
    ...
  end
end
```

Again if the block exits with a `return` or `break` the state will **not** be observed.

The `state_reader` method declares one or more state accessors with an implicit state observation:

```ruby
state_reader :bar, :baz
```

is equivilent to

```ruby
def bar
  observe @bar
end
def baz
  observe @baz
end
```

### Mutating State: `mutate, mutator, state_writer, toggle`

The `mutate` method takes any number of arguments and/or a block. The last argument evaluated or the value of the block is returned.

The arguments and block are evaluated then the object's state will be *mutated*.

If the block exits with a return or break, the state will **not** be mutated.

```ruby
# evaluate and return a value
mutate @history[@step]

# evaluate a block and return its value
mutate do
  @history[@step]
end
```

The `mutator` method defines a new method with an implicit mutate:

```ruby
mutator :foo do |x, y, z|
  ...
end
```

is equivilent to

```ruby
def foo(x, y, z)
  mutate do
    ...
  end
end
```

Again if the block exits with a `return` or `break` the state will **not** be mutated.

The `state_writer` method declares one or more state accessors with an implicit state mutation:

```ruby
state_reader :bar, :baz
```

is equivilent to

```ruby
def bar=(x)
  mutate @bar = x
end
def baz=(x)
  observe @baz = x
end
```

The `toggle` method reverses the polarity of a instance variable:

```ruby
toggle(:foo)
```

is equivilent to

```ruby
mutate @foo = !@foo
```

### The `state_accessor` Method

Combines `state_reader` and `state_writer` methods.

```ruby
state_accessor :foo, :bar
```

is equivilent to

```ruby
state_reader :foo, :bar
state_writer :foo, :bar
```

## Components and Stores

The standard `HyperComponent` base class includes `Hyperstack::State::Observable` so any `HyperComponent` has access to all of the above methods. A component also always **observes itself** so you never need to use `observe` within a component **unless** the state will be accessed outside the component. However once you start doing that you would be better off to move the state into a separate store.

> In addition components also act as the **Observers** in the system. What this means is that the current component that is running its render method is recording all stores that call `observe`, when a store mutates, then all the components that recorded observations will be rerendered.


# HyperRouter

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true) **HyperRouter is a DSL wrapper for** [**ReactRouter v4.x**](https://github.com/ReactTraining/react-router) **to provide client-side routing for Single Page Applications (SPA). As the user changes "pages" instead of reloading from the server your App will mount different components.**

## This Page Under Construction

## Usage

```ruby
class AppRouter
  include Hyperstack::Component
  include Hyperstack::Router::Helpers
  include Hyperstack::Router

  render(DIV) do
    UL do
      LI { Link('/') { 'Home' } }
      LI { Link('/about') { 'About' } }
    end
    Route('/', exact: true, mounts: Home)
    Route('/about', mounts: About)
  end
end

class Home
  include Hyperstack::Component
  render(DIV) do
    H2 { 'Home' }
  end
end
```

## DSL

### Router

This is the Router module which you include in your top level component:

```ruby
class MyRouter
  include Hyperstack::Component
  include Hyperstack::Router
end
```

With the base Router class, you can also specify the history you want to use.

This can be done either using a macro:

```ruby
class MyRouter
  include Hyperstack::Component
  include Hyperstack::Router

  history :browser  # this is the default option if no other is specified
end
```

The macro accepts three options: `:browser`, `:hash`, or `:memory`.

Or by defining the `history` method:

```ruby
class MyRouter
  include Hyperstack::Component
  include Hyperstack::Router

  def history
    self.class.browser_history
  end
end
```

### Rendering a Router

Use the `render` macro as normal. Note you cannot redefine the `render` instance method in a Router componenent

```ruby
class MyRouter
  ...

  render(DIV) do
    H1 { 'Hello world!' }
  end
end
```

### Routes

Routes are defined with special pseudo components you call inside the router/components. The router determines which of the routes to actually mount based on the current URL.

```ruby
class MyRouter
  ...

  render(DIV) do
    Route('/', mounts: HelloWorld)
  end
end

class HelloWorld
  render do
    H1 { 'Hello world!' }
  end
end
```

The `Route` method takes a url path, and these options:

* `mounts: Component` The component you want to mount when routed to
* `exact: Boolean` When true, the path must match the location exactly
* `strict: Boolean` When true, the path will only match if the location and path **both** have/don't have a trailing slash

The `Route` method can also take a block instead of the `mounts` option.

```ruby
class MyRouter
  ...

  render(DIV) do
    Route('/', exact: true) do
      H1 { 'Hello world!' }
    end
  end
end
```

The block will be given the match, location, and history data:

```ruby
class MyRouter
  ...

  render(DIV) do
    Route('/:name') do |match, location, history|
      H1 { "Hello #{match.params[:name]} from #{location.pathname}, click me to go back!" }
        .on(:click) { history.go_back }
    end
  end
end
```

* The `Hyperstack::Router::Helpers` is useful for components mounted by the router.
* This automatically sets the `match`, `location`, and `history` params,

  and also gives you instance methods with those names.
* You can use either `params.match` or just `match`.

  and gives you access to the `Route` method and more.
* This allows you to create inner routes as you need them.

```ruby
class MyRouter
  include Hyperstack::Component
  include Hyperstack::Router::Helpers
  include Hyperstack::Router

  render(DIV) do
    Route('/:name', mounts: Greet)
  end
end

class Greet
  include Hyperstack::Component
  include Hyperstack::Router::Helpers

  render(DIV) do
    H1 { "Hello #{match.params[:foo]}!" }
    Route(match.url, exact: true) do
      H2 { 'What would you like to do?' }
    end
    Route("#{match.url}/:activity", mounts: Activity)
  end
end

class Activity
  include Hyperstack::Component
  include Hyperstack::Router::Helpers
  include Hyperstack::Router

  render(DIV) do
    H2 { params.match.params[:activity] }
  end
end
```

Normally routes will **always** render alongside sibling routes that match as well.

```ruby
class MyRouter
  ...

  render(DIV) do
    Route('/goodbye', mounts: Goodbye)
    Route('/:name', mounts: Greet)
  end
end
```

### Switch

Going to `/goodbye` would match `/:name` as well and render `Greet` with the `name` param with the value 'goodbye'. To avoid this behavior and only render one matching route at a time, use a `Switch` component.

```ruby
class MyRouter
  ...

  render(DIV) do
    Switch do
      Route('/goodbye', mounts: Goodbye)
      Route('/:name', mounts: Greet)
    end
  end
end
```

Now, going to `/goodbye` would match the `Goodbye` route first and only render that component.

### Links

Links are provided by both the `Hyperstack::Router` and `Hyperstack::Router::Helper` modules.

The `Link` method takes a url path, and these options:

* `search: String` adds the specified string to the search query
* `hash: String` adds the specified string to the hash location

  it can also take a block of children to render inside it.

```ruby
class MyRouter
  ...

  render(DIV) do
    Link('/Gregor Clegane')

    Route('/', exact: true) { H1() }
    Route('/:name') do |match|
      H1 { "Will #{match.params[:name]} eat all the chickens?" }
    end
  end
end
```

### NavLinks

NavLinks are the same as Links, but will add styling attributes when it matches the current url

* `active_class: String` adds the class to the link when the url matches
* `active_style: String` adds the style to the link when the url matches
* `active: Proc` A proc that will add extra logic to determine if the link is active

```ruby
class MyRouter
  ...

  render(DIV) do
    NavLink('/Gregor Clegane', active_class: 'active-link')
    NavLink('/Rodrik Cassel', active_style: { color: 'grey' })
    NavLink('/Oberyn Martell',
            active: ->(match, location) {
              match && match.params[:name] && match.params[:name] =~ /Martell/
            })

    Route('/', exact: true) { H1() }
    Route('/:name') do |match|
      H1 { "Will #{match.params[:name]} eat all the chickens?" }
    end
  end
end
```

### Pre-rendering

Pre-rendering is automatically taken care for you under the hood.

## Setup

To setup HyperRouter:

* Install the gem
* Your page should render your router as its top-level-component (first component to be rendered on the page) - in the example below this would be `AppRouter`
* You will need to configure your server to route all unknown routes to the client-side router (Rails example below)

### With Rails

Assuming your router is called `AppRouter`, add the following to your `routes.rb`

```ruby
root 'Hyperstack#AppRouter' # see note below
match '*all', to: 'Hyperstack#AppRouter', via: [:get] # this should be the last line of routes.rb
```

Note:

`root 'Hyperstack#AppRouter'` is shorthand which will automagically create a Controller, View and launch `AppRouter` as the top-level Component. If you are rendering your Component via your own COntroller or View then ignore this line.

### Example

Here is the basic JSX example that is used on the [react-router site](https://reacttraining.com/react-router/)

```jsx
import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

const BasicExample = () => (
  <Router>
    <div>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/topics">Topics</Link></li>
      </ul>

      <hr/>

      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
      <Route path="/topics" component={Topics}/>
    </div>
  </Router>
)

const Home = () => (
  <div>
    <h2>Home</h2>
  </div>
)

const About = () => (
  <div>
    <h2>About</h2>
  </div>
)

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <ul>
      <li><Link to={`${match.url}/rendering`}>Rendering with React</Link></li>
      <li><Link to={`${match.url}/components`}>Components</Link></li>
      <li><Link to={`${match.url}/props-v-state`}>Props v. State</Link></li>
    </ul>

    <Route path={`${match.url}/:topicId`} component={Topic}/>
    <Route exact path={match.url} render={() => (
      <h3>Please select a topic.</h3>
    )}/>
  </div>
)

const Topic = ({ match }) => (
  <div>
    <h3>{match.params.topicId}</h3>
  </div>
)

export default BasicExample
```

And here is the same example in Hyperstack:

```ruby
class BasicExample
  include Hyperstack::Component
  include Hyperstack::Router::Helpers
  include Hyperstack::Router

  render(DIV) do
    UL do
      LI { Link('/') { 'Home' } }
      LI { Link('/about') { 'About' } }
      LI { Link('/topics') { 'Topics' } }
    end

    Route('/', exact: true, mounts: Home)
    Route('/about', mounts: About)
    Route('/topics', mounts: Topics)
  end
end

class Home
  include Hyperstack::Component
  include Hyperstack::Router::Helpers

  render(DIV) do
    H2 { 'Home' }
  end
end

class About  
  include Hyperstack::Component
  include Hyperstack::Router::Helpers

  render(:div) do
    H2 { 'About' }
  end
end

class Topics
  include Hyperstack::Component
  include Hyperstack::Router::Helpers

  render(DIV) do
    H2 { 'Topics' }
    UL() do
      LI { Link("#{match.url}/rendering") { 'Rendering with React' } }
      LI { Link("#{match.url}/components") { 'Components' } }
      LI { Link("#{match.url}/props-v-state") { 'Props v. State' } }
    end
    Route("#{match.url}/:topic_id", mounts: Topic)
    Route(match.url, exact: true) do
      H3 { 'Please select a topic.' }
    end
  end
end

class Topic
  include Hyperstack::Component
  include Hyperstack::Router::Helpers

  render(:div) do
    H3 { match.params[:topic_id] }
  end
end
```


# HyperModel

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true) HyperModel extends Rails ActiveRecord models so that you have direct access to them on the client, using the same ActiveRecord classes and methods as you would on the server. Nothing new to learn, or configure, just plug in and go.

## This Page Under Construction

In Hyperstack, your ActiveRecord Models are available in your Isomorphic code.

Components, Operations, and Stores have CRUD access to your server side ActiveRecord Models, using the standard ActiveRecord API.

In addition, Hyperstack implements push notifications (via a number of possible technologies) so changes to records on the server are dynamically pushed to all authorized clients.

In other words, one browser creates, updates, or destroys a Model, and the changes are persisted in ActiveRecord models and then broadcast to all other authorized clients.

* You access your Model data in your Components, Operations, and Stores just like you would on the server or in an ERB or HAML view file.
* If an optional push transport is connected Hyperstack broadcasts any changes made to your ActiveRecord models as they are persisted on the server or updated by one of the authorized clients.
* Some Models (or even parts of Models) can be designated as *server-only* which means they are not available to the client code.

For example, consider a simple model called `Dictionary` which might be part of Wiktionary type app.

```ruby
class Dictionary < ActiveRecord::Base

  # attributes
  #   word: string   
  #   definition: text
  #   pronunciation: string

  scope :defined, -> { 'definition IS NOT NULL AND pronunciation IS NOT NULL' }
end
```

Here is a very simple Hyperstack Component that shows a random word from the dictionary:

```ruby
class WordOfTheDay < Hyperstack::Component

  def pick_entry!  
    # pick a random word and assign the selected record to entry
    mutate @entry = Dictionary.defined[rand(Dictionary.defined.count)]
    # Notice that we use standard ActiveRecord constructs to select our
    # random entry value
  end

  # pick an initial entry before we mount our component...
  before_mount :pick_entry

  # Again in our render block we use the standard ActiveRecord API, such
  # as the 'defined' scope, and the 'word', 'pronunciation', and
  # 'definition' attribute getters.  
  render(DIV) do
    DIV { "total definitions: #{Dictionary.defined.count}" }
    DIV do
      DIV { @entry.word }
      DIV { @entry.pronunciation }
      DIV { @entry.definition }
      BUTTON { 'pick another' }.on(:click) { pick_entry! }
    end
  end
```

**This is the entire code. There are no application APIs needed. The synchronization between server and client is completely taken care of by HyperModel. If you have an existing code base little to updates to your existing Models is needed, and you will use the same ActiveRecord API you have been using.**

## Isomorphic Models

Depending on the architecture of your application, you may decide that some of your models should be Isomorphic and some should remain server-only. The consideration will be that your Isomorphic models will be compiled by Opal to JavaScript and accessible on he client (without the need for a boilerplate API) - Hyperstack takes care of the communication between your server-side models and their client-side compiled versions and you can use Policy to govern access to the models.

In order for Hyperstack to see your Models (and make them Isomorphic) you need to move them to the `hyperstack/models` folder. Only models in this folder will be seen by Hyperstack and compiled to Javascript. Once a Model is on this folder it ill be accessable to both your client and server code.

| **Location of Models**  | **Scope**                           |
| ----------------------- | ----------------------------------- |
| `app\models`            | Server-side code only               |
| `app\hyperstack\models` | Isomorphic code (client and server) |

## ActiveRecord API

Hyperstack uses a subset of the standard ActiveRecord API to give your Isomorphic Components, Operations and Stores access to your server side Models. As much as possible Hyperstack follows the syntax and semantics of ActiveRecord.

### Interfacing to React

Hyperstack integrates with React (through Components) to deliver your Model data to the client without you having to create extra APIs or specialized controllers. The key idea of React is that when state (or params) change, the portions of the display effected by this data will be updated.

On the client each database record being used by the client is represented as an observable store **(**[**see the chapter on HyperState for details**](https://github.com/hyperstack-org/hyperstack/tree/eb3b1ae153cabb1ccad6d93d5a5e98c2fd4bb434/docs/hyper-model/hyper-state/README.md)**)** which will mutate as server side data is loaded or changes. When these states change the associated parts of the display will be updated.

A brief overview of how this works will help you understand the how HyperStack gets the job done.

#### Rendering Cycle

On the UI you will be reading models in order to display data.

If during the rendering of the display the Model data is not yet loaded, placeholder values (the default values from the database schema) will be returned by Hyperstack.

Hyperstack then keeps track of where these placeholders (or `DummyValue`s) are displayed, and when they do get loaded, those parts of the display will re-render.

If later the data changes (either due to local user actions, or receiving push updates) then again any parts of the display that were dependent on the current values will be re-rendered.

You normally do not have to be aware of this. Just access your Models using the normal scopes and finders, then compute values and display attributes as you would on the server. Initially the display will show the placeholder values and then will be replaced with the real values.

#### Prerendering

During server-side pre-rendering, Hyperstack has direct access to the server so on initial page load all the values will be loaded and present.

#### Lazy Loading

Hyperstack lazy loads values, and does not load any thing until an explicit displayable value is requested. For example `Todo.all` will have no action, but `Todo.all.pluck[:title]` will return an array of titles.

At the end of the rendering cycle the set of all values requested will be merged into a tree structure and sent to the server, returning the minimum amount of data needed.

#### Load Cycle Methods

There are a number of methods that allow you to interact with this load cycle when needed. These are documented [below](https://github.com/hyperstack-org/hyperstack/tree/eb3b1ae153cabb1ccad6d93d5a5e98c2fd4bb434/docs/hyper-model/hyper-model.md#other-methods-for-interacting-with-the-load-and-render-cycle).

### Class Methods

#### New and Create

`new`: Takes a hash of attributes and initializes a new unsaved record. The values of any attributes not specified in the hash will be taken from the Models default values specified in the data base schema.

If `new` is passed a native javascript object it will be treated as a hash and converted accordingly.

`create`: Short hand for `new(...).save`. See the `save` instance method for details on how saving is done.

#### Scoping and Finding

`scope` and `default_scope`: Hyperstack adds four new options to these methods: `joins`, `client`, `select` and `server`. The `joins` option provides information on how the scope will be joined with other models. The `client` and `select` options allow scoping to be done on the client side to offload this from the server, and the `server` option is there just for symmetry with the other options.

```ruby
# the active scope proc is executed on the server
scope :active, -> () { where(completed: true) }

# if the scope does a join (or include) this must be indicated
# using the joins: option.
scope :with_recent_comments,
      -> { joins(:comments).where('comment.created_at >= ?', Time.now-1.week) },
      joins: ['comments'] # or joins: 'comments'

# the server side proc can be indicated by the server: option
# an optional client side proc can be provided to compute the scope
# locally at the client
scope :completed,
      server: -> { where(complete: true) }
      client: -> { complete } # return true if the record should be included
```

`unscoped` and `all`: These builtin scopes work just like standard ActiveRecord.

BTW: to save typing you can skip the `all`: Models will respond like enumerators.

```ruby
Word.all.each { |word| LI { word.text }}
```

`where`: The where method can be used to filter records:

```ruby
Word.where("LENGTH(text) = ?", n)
```

> The `where` method is implemented internally as a scope on the client that will execute the where method on the server. If the parameters to the where method the scope will be updated on the client, but using SQL in the where as in the above example will get executed on the server.

`find`: takes an id and delivers the corresponding record.

`find_by`: takes a single item hash indicating an attribute value pair to find.

`find_by_...`: i.e. `find_by_first_name` these methods will find the first record with a matching attribute.

```ruby
Word.find_by_text('hello') # short for Word.find_by(text: 'hello')
```

`limit` and `offset`: These builtin scopes behave as they do on the server:

```ruby
Word.offset(500).limit(20) # get words 500-519
```

#### Applying Class Methods to Collections

Like Rails if you define a class method on a model, you can apply it to a collection of those records, allowing you to chain methods with scopes (and relationships)

```ruby
class Word < ApplicationRecord
  def self.page(pg)
    offset(pg-1 * 20).limit(20)
  end
end
...
  Word.some_scope.page(3)
```

#### Relationships and Aggregations

`belongs_to, has_many, has_one`: These all work as on the server. **However it is important that you fully specify both sides of the relationship.**

```ruby
class Todo < ActiveRecord::Base
  belongs_to :assigned_to, class_name: 'User'
end

class User < ActiveRecord::Base
  has_many :todos, foreign_key: 'assigned_to_id'
end
```

Note that on the client the linkages between relationships are live and direct. In the above example this works:

```ruby
Todo.create(assigned_to: some_user)
```

but this may not:

```ruby
Todo.create(assigned_to_id: some_user.id)
```

`composed_of`: You can create aggregate models like ActiveRecord.

Similar to the linkages in relationships, aggregate records are represented on the client as actual independent objects.

#### Defining server methods

Normally an application defined instance method will run on the client and the server:

```ruby
class User < ActiveRecord::Base
  def full_name
    "#{first_name} #{last_name}"
  end
end
```

Sometimes it is desirable to only run the method on the server. This can be done using the `server_method` macro:

```ruby
class User < ActiveRecord::Base
  server_method :full_name, default: '' do
    "#{first_name} #{last_name}"
  end
end
```

When the method is first called on the client the default value will be returned, and there will be a reactive update when the true value is returned from the server.

To force the value to be recomputed at the server append a `!` to the end of the name, otherwise the last value returned from the server will continue to be returned.

#### Model Information

`column_names`: returns a list of the database columns.

`columns_hash`: returns the details of the columns specification. Note that on the server `columns_hash` returns a hash of objects specifying column information. On the client the entire structure is just one big hash of hashes.

`abstract_class=`, `abstract_class?`, `primary_key`, `primary_key=`, `inheritance_column`, `inheritance_column=`, `model_name`: All work as on the server. See ActiveRecord documentation for more info.

### Instance Methods

#### Attribute and Relationship Getter and Setters

All attributes have an associated getter and setter. All relationships have a getter. All `belongs_to` relationships also have a setter. `has_many` relationships can be updated using the push (`<<`) operator or using the `delete` method.

```ruby
  puts my_todo.title
  my_todo.title = "neutitle"
  my_todo.comments << a_new_comment
  a_new_comment.todo == my_todo # true!
```

In addition if the attribute getter ends with a bang (!) then this will force a fetch of the attribute from the server. This is typically not necessary if push updates are configured.

#### Saving

The `save` method works like ActiveRecord save, *except* it returns a promise that is resolved when the save completes (or fails.)

```ruby
my_todo.save(validate: false).then do |result|
  # result is a hash with {success: ..., message: , models: ....}
end
```

After a save operation completes the models will have an `errors` hash (just like on the server) with any validation problems.

During the save operation the method `saving?` will return `true`. This can be used to instead of (or with) the promise to update the screen:

```ruby
render do
  ...
  if some_model.saving?
    ... display please wait ...
  elsif some_model.errors.any?
    ... highlight the errors ...
  else
    ... display data ...
  end
  ...
end
```

#### Destroy

Like `save` destroy returns a promise that is resolved when the destroy completes.

After the destroy completes the record's `destroyed?` method will return true.

#### Other Instance Methods

`new?` returns true if the model is new and not yet saved.

`primary_key` returns the primary key for the model

`id` returns the value of the primary key for this instance

`model_name` returns the model\_name.

`revert` Undoes any unsaved changes to the instance.

`changed?` returns true if any attributes have changed (always true for a new model)

`dup` duplicate the instance.

`==` two instances are the same if it is known that they reference the same underlying table row.

`..._changed?` (i.e. name\_changed?) returns true if the specific attribute has changed.

`itself` returns the record, but will override lazy loading and force a load of at least the model's id.

### Load and Render Cycle

#### loading? and loaded?

All Ruby objects will respond to these methods. If you want to put up a "Please Wait" message, spinner, etc, you can use the `loaded?` or `loading?` method to determine if the object represents a real loaded value or not. Any value for which `loaded?` returns `false` (or `loading?` returns `true`) will eventually load and cause a re-render

#### Hyperstack::Model.load method

Sometimes it is necessary to insure values are loaded outside of the rendering cycle. For this you can use the `Hyperstack::Model.load` method:

```ruby
Hyperstack::Model.load do
  x = my_model.some_attribute
  OtherModel.find(x+12).other_attribute
  # code in here can be arbitrarily complex and load
  # will re-execute it until all values are loaded
  # the final expression is passed to the promise
end.then |result|
  puts result
end
```

#### Force Loading Attributes

Normally you will simply display attributes as part of the render method, and when the values are loaded from the server the component will re-render.

Sometimes outside of the render method you may need to insure an attribute (or a server side method) is loaded before proceeding. This is typically when you are building some kind of higher level store.

The `load` method takes a list of attributes (symbols) and will insure these are loaded. Load returns a promise that is resolved when the load completes, or can be passed a block that will execute when the load completes.

```ruby
before_mount do
  Todo.find(1).load(:name).then do |name|
    @name = name;
    state.loaded! true
  end
end
```

Think hard about how you are using this, as Hyperstack already acts as flux store, and is managing state for you. It may be you are just creating a redundant store!

## Client Side Scoping

By default scopes will be recalculated on the server. For simple scopes that do not use joins or includes no additional action needs to be taken to make scopes work with Hyperstack. For scopes that do use joins, or if you want to offload the scoping computation from the server to the client read this section.

## ActiveRecord Scope Enhancement

When the client receives notification that a record has changed Hyperstack finds the set of currently rendered scopes that might be effected, and requests them to be updated from the server.

On the server scopes are a useful way to structure code. **On the client** scopes are vital as they limit the amount of data loaded, viewed, and updated in the browser. Consider a factory floor management system that shows *job* state as work flows through the factory. There may be millions of jobs that a production floor browser is authorized to view, but at any time there are probably only 50 being shown. Using ActiveRecord scopes is the way Hyperstack keeps the data requested by the browser limited to a reasonable amount.

To make scopes work efficiently on the client Hyperstack adds some features to the ActiveRecord `scope` and `default_scope` macros. Note you must use the `scope` macro (and not class methods) for things to work with Hyperstack.

The additional features are accessed via the `:joins`, `:client`, and `:select` options.

The `:joins` option tells the Hyperstack client which models are joined with the scope. *You must add a `:joins` option if the scope has any data base join operations in it, otherwise if a joined model changes, Hyperstack will not know to update the scope.*

The `:client` and `:select` options provide the client a way to update scopes without having to contact the server. Unlike the `:joins` option this is an optimization and is not required for scopes to work.

```ruby
class Todo < ActiveRecord::Base

  # Standard ActiveRecord form:
  # the proc will be evaluated as normal on the server, and as needed updates
  # will be requested from the clients

  scope :active, -> () { where(completed: true) }

  # In the simple form the scope will be reevaluated if the model that is
  # being scoped changes, and if the scope is currently being used to render data.

  # If the scope joins with other data you will need to specify this by
  # passing a relationship or array of relationships to the `joins` option.

  scope :with_recent_comments,
        -> { joins(:comments).where('comment.created_at >= ?', Time.now-1.week) },
        joins: ['comments'] # or joins: 'comments'

  # Now with_recent_comments will be re-evaluated whenever a Todo record, or a Comment
  # joined with a Todo change.

  # Normally whenever Hyperstack detects that a scope may be effected by a changed
  # model, it will request the scope be re-evaluated on the server.  To offload this
  # computation to the client provide a client side scope method:

  scope :with_recent_comments,
        -> { joins(:comments).where('comment.created_at >= ?', Time.now-1.week) },
        joins: ['comments']
        client: -> { comments.detect { |comment| comment.created_at >= Time.now-1.week }

  # The client proc is executed on each candidate record, and if it returns true the record
  # will be added to the scope.

  # Instead of a client proc you can provide a select proc, which will receive the entire
  # collection which can then be filtered and sorted.

  scope :sort_by_created_at,
        -> { order('created_at DESC') }
        select: -> { sort { |a, b| b.created_at <=> a.created_at }}

  # To keep things tidy you can specify the server scope proc with the :server option

  scope :completed,
        server: -> { where(complete: true) }
        client: -> { complete }

  # The expressions in the joins array can be arbitrary sequences of relationships and
  # scopes such as 'comments.author'.  

  scope :with_managers_comments,
        server: -> { ... }
        joins: ['comments.author', 'owner']
        client: -> { comments.detect { |comment| comment.author == owner.manager }}}

  # You can also use the client, select, server, and joins option with the default_scope macro

  default_scope server: -> { where(deleted: false).order('updated_at DESC') }
                select: -> { select { |r| !r.deleted }.sort { |a, b| b <=> a } }

  # NOTE: it is highly recommend to provide a client proc with default_scopes.  Otherwise
  # every change is going to require a server interaction regardless of what other client procs
  # you provide.

end
```

#### How it works

Consider this scope on the Todo model

```ruby
scope :with_managers_comments,
      server: -> { joins(owner: :manager, comments: :author).where('managers_users.id = authors_comments.id').distinct },
      client: -> { comments.detect { |comment| comment.author == owner.manager }}
      joins: ['comments.author', 'owner']
```

The joins 'comments.author' relationship is inverted so that we have User 'has\_many' Comments which 'belongs\_to' Todos.

Thus we now know that whenever a User or a Comment changes this may effect our with\_managers\_comments scope

Likewise 'owner' becomes User 'has\_many' Todos.

Lets say that a user changes teams and now has a new manager. This means according to the relationships that the User model will change (i.e. there will be a new manager\_id in the User model) and thus all Todos belonging to that User are subject to evaluation.

While the server side proc efficiently delivers all the objects in the scope, the client side proc just needs to incrementally update the scope.

## Configuring the Transport

Hyperstack implements push notifications (via a number of possible technologies) so changes to records on the server are dynamically pushed to all authorized clients.

The can be accomplished by configuring **one** of the push technologies below:

| Push Technology                                                                                                                                                        | When to choose this...                                                                                                                                                                                                                   |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Simple Polling](https://github.com/hyperstack-org/hyperstack/tree/eb3b1ae153cabb1ccad6d93d5a5e98c2fd4bb434/docs/hyper-model/hyper-model.md#setting-up-simple-polling) | The easiest push transport is the built-in simple poller.  This is great for demos or trying out Hyperstack but because it is constantly polling it is not suitable for production systems or any kind of real debug or test activities. |
| [Action Cable](https://github.com/hyperstack-org/hyperstack/tree/eb3b1ae153cabb1ccad6d93d5a5e98c2fd4bb434/docs/hyper-model/hyper-model.md#setting-up-action-cable)     | If you are using Rails 5 this is the perfect route to go. Action Cable is a production ready transport built into Rails 5.                                                                                                               |
| [Pusher.com](https://github.com/hyperstack-org/hyperstack/tree/eb3b1ae153cabb1ccad6d93d5a5e98c2fd4bb434/docs/hyper-model/hyper-model.md#setting-up-pusher-com)         | Pusher.com is a commercial push notification service with a free basic offering. The technology works well but does require a connection to the internet at all times.                                                                   |
| [Pusher Fake](https://github.com/hyperstack-org/hyperstack/tree/eb3b1ae153cabb1ccad6d93d5a5e98c2fd4bb434/docs/hyper-model/hyper-model.md#setting-up-pusher-fake)       | The Pusher-Fake gem will provide a transport using the same protocol as pusher.com but you can use it to locally test an app that will be put into production using pusher.com.                                                          |

### Setting up Simple Polling

The easiest push transport is the built-in simple poller. This is great for demos or trying out Hyperstack but because it is constantly polling it is not suitable for production systems or any kind of real debug or test activities.

Simply add this initializer:

```ruby
#config/initializers/Hyperstack.rb
Hyperstack.configuration do |config|
  config.transport = :simple_poller
  # options
  # config.opts = {
  #   seconds_between_poll: 5, # default is 0.5 you may need to increase if testing with Selenium
  #   seconds_polled_data_will_be_retained: 1.hour  # clears channel data after this time, default is 5 minutes
  # }
end
```

That's it. Hyperstack will use simple polling for the push transport.

### Setting up Action Cable

To configure Hyperstack to use Action Cable, add this initializer:

```ruby
#config/initializers/Hyperstack.rb
Hyperstack.configuration do |config|
  config.transport = :action_cable
end
```

If you are already using ActionCable in your app that is fine, as Hyperstack will not interfere with your existing connections.

**Otherwise** go through the following steps to setup ActionCable.

Firstly, make sure the `action_cable` js file is required in your assets.

Typically `app/assets/javascripts/application.js` will finish with a `require_tree .` and this will pull in the `cable.js` file which will pull in `action_cable.js`

However at a minimum if `application.js` simply does a `require action_cable` that will be sufficient for Hyperstack.

Make sure you have a cable.yml file:

```
# config/cable.yml
development:
  adapter: async

test:
  adapter: async

production:
  adapter: redis
  url: redis://localhost:6379/1
```

Set allowed request origins (optional):

**By default action cable will only allow connections from localhost:3000 in development.** If you are going to something other than localhost:3000 you need to add something like this to your config:

```ruby
# config/environments/development.rb
Rails.application.configure do
  config.action_cable.allowed_request_origins = ['http://localhost:3000', 'http://localhost:5000']
end
```

That's it. Hyperstack will use Action Cable as the push transport.

### Setting up Pusher.com

[Pusher.com](https://pusher.com/) provides a production ready push transport for your App. You can combine this with [Pusher-Fake](https://github.com/hyperstack-org/hyperstack/tree/a530e3955296c5bd837c648fd452617e0a67a6ed/docs/pusher_faker_quickstart.md) for local testing as well. You can get a free pusher account and API keys at <https://pusher.com>

First add the Pusher and Hyperstack gems to your Rails app:

add `gem 'pusher'` to your Gemfile.

Next Add the pusher js file to your application.js file:

```ruby
# app/assets/javascript/application.js
...
//= require 'Hyperstack/pusher'
//= require_tree .
```

Finally set the transport:

```ruby
# config/initializers/Hyperstack.rb
Hyperstack.configuration do |config|
  config.transport = :pusher
  config.channel_prefix = "Hyperstack"
  config.opts = {
    app_id: "2....9",
    key: "f.....g",
    secret: "1.......3"
  }
end
```

That's it. You should be all set for push notifications using Pusher.com.

### Setting up Pusher Fake

The [Pusher-Fake](https://github.com/tristandunn/pusher-fake) gem will provide a transport using the same protocol as pusher.com. You can use it to locally test an app that will be put into production using pusher.com.

Firstly add the Pusher, Pusher-Fake and Hyperstack gems to your Rails app

* add `gem 'pusher'` to your Gemfile.
* add `gem 'pusher-fake'` to the development and test sections of your Gemfile.

Next add the pusher js file to your application.js file

```ruby
# app/assets/javascript/application.js
...
//= require 'Hyperstack/pusher'
//= require_tree .
```

Add this initializer to set the transport:

```ruby
# typically app/config/initializers/Hyperstack.rb
# or you can do a similar setup in your tests (see this gem's specs)
require 'pusher'
require 'pusher-fake'
# Assign any values to the Pusher app_id, key, and secret config values.
# These can be fake values or the real values for your pusher account.
Pusher.app_id = "MY_TEST_ID"      # you use the real or fake values
Pusher.key =    "MY_TEST_KEY"
Pusher.secret = "MY_TEST_SECRET"
# The next line actually starts the pusher-fake server (see the Pusher-Fake readme for details.)
# it is important this require be AFTER the above settings, as it will use these
require 'pusher-fake/support/base' # if using pusher with rspec change this to pusher-fake/support/rspec
# now copy over the credentials, and merge with PusherFake's config details
Hyperstack.configuration do |config|
  config.transport = :pusher
  config.channel_prefix = "Hyperstack"
  config.opts = {
    app_id: Pusher.app_id,
    key: Pusher.key,
    secret: Pusher.secret
  }.merge(PusherFake.configuration.web_options)
end
```

That's it. You should be all set for push notifications using Pusher Fake.

## Debugging

Sometimes you need to figure out what connections are available, or what attributes are readable etc.

Its usually all to do with your policies, but perhaps you just need a little investigation.

TODO check rr has become Hyperstack (as below)

You can bring up a console within the controller context by browsing `localhost:3000/Hyperstack/console`

**Note: change `rr` to wherever you are mounting Hyperstack in your routes file.**

**Note: in rails 4, you will need to add the gem 'web-console' to your development section**

Within the context you have access to `session.id` and current `acting_user` which you will need, plus some helper methods to reduce typing

* Getting auto connection channels: `channels(session_id = session.id, user = acting_user)` e.g. `channels` returns all channels connecting to this session and user providing nil as the acting\_user will test if connections can be made without there being a logged in user.
* Can a specific class connection be made: `can_connect?(channel, user = acting_user)` e.g. `can_connect? Todo` returns true if current acting\_user can connect to the Todo class. You can also provide the class name as a string.
* Can a specific instance connection be made: `can_connect?(channel, user = acting_user)` e.g. `can_connect? Todo.first` returns true if current acting\_user can connect to the first Todo Model. You can also provide the instance in the form 'Todo-123'
* What attributes are accessible for a Model instance: `viewable_attributes(instance, user = acting_user)`
* Can the attribute be viewed: `view_permitted?(instance, attribute, user = acting_user)`
* Can a Model be created/updated/destroyed: `create_permitted?(instance, user = acting_user)` e.g. `create_permitted?(Todo.new, nil)` can anybody save a new todo? e.g. `destroy_permitted?(Todo.last)` can the acting\_user destroy the last Todo

You can of course simulate server side changes to your Models through this console like any other console. For example

`Todo.new.save` will broadcast the changes to the Todo Model to any authorized channels.

## Common Errors

* **No policy class** If you don't define a policy file, nothing will happen because nothing will get connected. By default Hyperstack will look for a `ApplicationPolicy` class.
* **Wrong version of pusher-fake** (pusher-fake/base vs. pusher-fake/rspec) See the Pusher-Fake gem repo for details.
* Forgetting to add `require pusher` in application.js file this results in an error like this:

  ```
  Exception raised while rendering #<TopLevelRailsComponent:0x53e>
      ReferenceError: Pusher is not defined
  ```

  To resolve make sure you `require 'pusher'` in your application.js file if using pusher. DO NOT require pusher from your components manifest as this will cause prerendering to fail.
* **No create/update/destroy policies** You must explicitly allow changes to the Models to be made by the client. If you don't you will see 500 responses from the server when you try to update. To open all access do this in your application policy: `allow_change(to: :all, on: [:create, :update, :destroy]) { true }`
* **Cannot connect to real pusher account** If you are trying to use a real pusher account (not pusher-fake) but see errors like this

  ```
  pusher.self.js?body=1:62 WebSocket connection to
  'wss://127.0.0.1/app/PUSHER_API_KEY?protocol=7&client=js&version=3.0.0&flash=false'
  failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
  ```

  Check to see if you are including the pusher-fake gem. Hyperstack will always try to use pusher-fake if it sees the gem included. Remove it and you should be good to go. See [issue #5](https://github.com/hyper-react/HyperMesh/issues/5) for more details.
* **Cannot connect with ActionCable.** Make sure that `config.action_cable.allowed_request_origins` includes the url you use for development (including the port) and that you are using `Puma`.
* **Attributes are not being converted from strings, or do not have their default values** Eager loading is probably turned off. Hyperstack needs to eager load `Hyperstack/models` so it can find all the column information for all Isomorphic models.
* **When starting rails you get a message on the rails console `couldn't find file 'browser'`** The `hyper-component` v0.10.0 gem removed the dependency on opal-browser. You will have to add the 'opal-browser' gem to your Gemfile.
* **On page load you get a message about super class mismatch for `DummyValue`** You are still have the old `reactive-record` gem in your Gemfile, remove it from your gemfile and your components manifest.
* **On page load you get a message about no method `session` for `nil`** You are still referencing the old reactive-ruby or reactrb gems either directly or indirectly though a gem like reactrb-router. Replace any gems like `reactrb-router` with `hyper-router`. You can also just remove `reactrb`, as `hyper-model` will be included by the `hyper-model` gem.
* **You keep seeing the message `WebSocket connection to 'ws://localhost:3000/cable' failed: WebSocket is closed before the connection is established.`** every few seconds in the console. There are probably lots of reasons for this, but it means ActionCable can't get itself going. One reason is that you are trying to run with Passenger instead of Puma, and trying to use `async` mode in cable.yml file. `async` mode requires Puma.


# Operations

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true) HyperOperations are HyperStack's implementation of Service Objects based on Trailblazer Operations. Operations can be used on the client, the server, or can act like a remote procedure call mechanism communicating between the client and the server.

## This Page Under Construction

> "A class that performs an action" [A simple explanation of Service Objects for Ruby on Rails](https://medium.freecodecamp.org/service-objects-explained-simply-for-ruby-on-rails-5-a8cc42a5441f)

Why do we need Service Objects? Because in any real world system you have logic that does not belong in models (or stores) because it effects multiple models or stores, and it does not belong in components because the logic of the task is independent of the specific user interface design. In MVC frameworks this kind of logic is often shoved in the controller, but it doesn't belong there either.

There are also those boundary areas between gathering and processing external data and getting data into or out of our stores and models. You don't want that kind of logic in your model or store, so where does it go? It belongs in a service object or *Operation* in Hyperstack terminology.

> The term Operation, the key concepts of the Operation, and a lot of the implementation was taken from [Trailblazer](http://trailblazer.to/guides/trailblazer/2.0/01-operation-basics.html)

Simply put an Operation is like a large standalone method that has no internal state of its own. You run an operation, it does it thing, and it returns an answer.

Any state that an operation needs to retrieve or save is stored somewhere else: in a model, a store, or even in a remote API. Once the operation completes, it has no memory of its own.

Being a stand-alone, glue and business logic method is an Operation's full time mission. The Hyperstack `Operation` base class is therefor structured to make writing this kind of code easy.

* An Operation may take parameters (params) just like any other method; &#x20;
* An Operation may validate the parameters;
* An Operation then executes a number of *steps*;
* The steps can be part of a success track or a failure track;
* The value of the final step is returned to the caller;
* And the results can be *broadcast* to any interested parties.

Hyperstack's Operations often involve asynchronous methods such as HTTP requests and so Operations always return *Promises*. Likewise each of the steps of an Operation can itself be an asynchronous action, and the Operation class will take care of chaining the promises together for you.

Another key feature of Operations is that because they are stateless they make a perfect RPC (Remote Procedure Call) mechanism. So an Operation can be called on the client, but will run on the server, and then return or broadcast the results to the clients. Thus Operations form the underlying data *transport* mechanism between the server and clients.

That is a lot to digest, and truly Operations are the swiss-army knife of Hyperstack. So let's dive into some examples.

In this simple example we are going to use a third-party API to determine our browser's IP address. First without Operations:

```ruby
class App < HyperComponent
  before_mount do
    HTTP.get('https://api.ipify.org?format=json').then do |response|
      mutate @ip_address = response.json[:ip]
    end
  end

  render do
    H1 { "Hello world from Hyperstack your ip address: #{@ip_address}" }
  end
end
```

Nice and simple. Our App mounts, does a HTTP get from our API, and when it returns it updates the state. The problem is our view logic is cluttered up with low level specifics of how to get the address. Lets fix that by moving that logic to a separate service object:

```ruby
class GetIPAddress
  def self.run
    HTTP.get('https://api.ipify.org?format=json').then do |response|
      response.json[:ip]
    end
  end
end
```

Notice that the object is stateless and because it has no state it is simply a class method. We then use our service object like this:

```ruby
class App < HyperComponent
  before_mount do
    GetIPAddress.run.then { |ip_address| mutate @ip_address = ip_address}
  end

  render do
    H1 { "Hello world from Hyperstack.  Your ip address is #{@ip_address}" }
  end
end
```

If we were to change how we get the IP address, the Component now doesn't have to change.

Now we will redefine our service object using the Hyperstack::Operation class.

```ruby
class GetIPAddress < Hyperstack::Operation
  step { HTTP.get('https://api.ipify.org?format=json') }
  step { |response| response.json[:ip] }
end
```

You invoke Operations using the run method, so our Component does not have to change at all.

The advantage is that the Operation syntax takes care of a lot of clutter, allows our promise to be chained neatly, and makes our intention clear to the reader.

We will see how these advantages multiply as our example becomes more complex.

Before moving on lets understand the basics of Operations.

* Every Operation has as its external API a single `run` method.
* The work of the Operation is defined by a series of *steps*.
* When the run method is called, the code associated with each step is executed.
* If a step returns a promise the next step will wait till the promise is resolved.
* The result of the final step is wrapped in a promise and is the result of the operation.

The final point means that regardless of the Operation's internal implementation, the Operation always returns a promise, so its API is consistent. As operations always return promises you can simply apply the `then` and `fail` promise methods directly to the Operation rather than saying `Op.run.then`.

Let's say that rather than a simple ip address what we want is a full set of geo-location data. We can use another third party API to do the job. This API requires we supply our IP address, so we will reuse our IPAddress Op.

```ruby
class GetGeoData < Hyperstack::Operation
  step GetIPAddress
  step { |ip_address| HTTP.get("https://ipapi.co/#{ip_address}/json/") }
  step { |response| response.json }
end
```

Here we can see one of the different ways to define a step: We simply delegate the first step to our already defined `GetIPAddress` operation.

Again lets compare to a traditional ServiceObject:

```ruby
class GetGeoData
  def self.run
    IPAddress.run.then do |ip_address|
      HTTP.get("https://ipapi.co/#{ip_address}/json/")
    end.then do |response|
      response.json
    end
  end
end
```

Again its the same logic, but the body of our service object is over twice the number of lines and logic is obscured by the promise handlers.

It would be nice if we could include a flag icon to go with the country in the response data. Lets do that:

```ruby
class GetGeoData < Hyperstack::Operation
  step IPAddress
  step { |ip_address| HTTP.get("https://ipapi.co/#{ip_address}/json/") }
  step { |response| response.json }
  step { |json| json.merge flag_url: "https://www.countryflags.io/#{json['country']}/shiny/64.png" }
end
```

Of course its just *Ruby*, so we can further clean up our code by defining some helper methods:

```ruby
class GetGeoData < Hyperstack::Operation
  step IPAddress
  step { |ip_address| HTTP.get(geo_data_url_for(ip_address)) }
  step { |response|   response.json }
  step { |json|       json.merge flag_url: flag_url_for(json['country']) }

  def geo_data_url_for(ip_address)
    "https://ipapi.co/#{ip_address}/json/"
  end

  def flag_url_for(country_code)
    "https://www.countryflags.io/#{country_code}/shiny/64.png"
  end
end
```

Our `GetGeoData` uses two remote third party operations, which may occasionally fail so we add a retry mechanism. This will introduce four new features of Operation: The *failure track*, *parameters*, and the `abort!` and `succeed!` methods.

Tracks

Operations have two *tracks* of execution. The normal success track which is defined by the `step` method, and a *failure track* which is defined by a series of `failed` methods.

Execution begins with the first step, and continues with each step until an exception is raised, or a promise fails. When that happens execution jumps *to the next* `failed` step, and the continues executing `failed` steps. The result of the Operation will be value of the last failed step, and the Operation's promise will be be rejected (i.e. will be in the fail state.)

Parameters

Operations can take a series of named parameters defined by the `param` method. Parameters can have type information, defaults, and can be validated. This helps Operations act like a firewall between various parts of the system, making debugging and error handling easier. For now we are just going to use a simple case of a parameter that takes a default value.

The `abort!` and `succeed!` methods

These provide an early exit like `return`, `break` and next statements. Calling `abort!` and `succeed!` immediately exits the Operation by the appropriate track.

Putting it together:

```ruby
class GetGeoData < Hyperstack::Operation
  param  attempts: 0

  step   IPAddress
  step   { |ip_address| HTTP.get(geo_data_url_for(ip_address)) }
  step   { |response|   response.json }
  step   { |json|       json.merge flag_url: flag_url_for(json['country']) }

  failed { abort! if params.attempts > 3 }
  failed { sleep 1.second }
  failed { GeoData.run(attempts: params.attempts+1).then(&:succeed!) }

  def geo_data_url_for(ip_address)
    "https://ipapi.co/#{ip_address}/json/"
  end

  def flag_url_for(country_code)
    "https://www.countryflags.io/#{country_code}/shiny/64.png"
  end
end
```

; they orchestrate the interactions between Components, external services, Models, and Stores. Operations provide a tidy place to keep your business logic.

Operations receive parameters, va and execute a series of steps They have a simple structure which is not dissimilar to a Component:

```ruby
class SimpleOperation < Hyperstack::Operation
  param :anything
  step { do_something }
end

#to invoke from anywhere
SimpleOperation.run(anything: :something)
.then { success }
.fail { fail }
```

Hyperstack's Isomorphic Operations span the client and server divide automagically. Operations can run on the client, the server, and traverse between the two.

This goal of this documentation is to outline Operations classes and provides enough information and examples to show how to implement Operations in an application.

### Operations have three core functions

Operations are packaged as one neat package but perform three different functions:

1. Operations encapsulate business logic into a series of steps
2. Operations can dispatch messages (either on the client or between the client and server)
3. ServerOps can be used to replace boiler-plate APIs through a bi-directional RPC mechanism

**Important to understand:** There is no requirement to use all three functions. Use only the functionality your application requires.

## Operations encapsulate business logic

In a traditional MVC architecture, the business logic ends up either in Controllers, Models, Views or some other secondary construct such as service objects, helpers, or concerns. In Hyperstack, Operations are first class objects who's job is to mutate state in the Stores, Models, and Components. Operations are discreet logic, which is of course, testable and maintainable.

An Operation does the following things:

1. receives incoming parameters, and does basic validations &#x20;
2. performs any further validations &#x20;
3. executes the operation &#x20;
4. dispatches to any listeners &#x20;
5. returns the value of the execution (step 3)

These are defined by series of class methods described below.

### Operation Structure

`Hyperstack::Operation` is the base class for an *Operation*

As an example, here is an Operation which ensures that the Model being saved always has the current `created_by` and `updated_by` `Member`.

```ruby
class SaveWithUpdatingMemberOp < Hyperstack::Operation
  param :model
  step { params.model.created_by = Member.current if params.model.new? }
  step { params.model.updated_by = Member.current }
  step { model.save.then { } }
end
```

This Operation is run from anywhere in the client or server code:

```ruby
SaveWithUpdatingMemberOp.run(model: MyModel)
```

Operations always return Promises, and those Promises can be chained together. See the section on Promises later in this documentation for details on how Promises work.

Operations can invoke other Operations so you can chain a sequence of `steps` and Promises which proceed unless the previous `step` fails:

```ruby
class InvoiceOpertion < Hyperstack::Operation
  param :order, type: Order
  param :customer, type: Customer

  step { CheckInventoryOp.run(order: params.order) }
  step { BillCustomerOp.run(order: params.order, customer: params.customer) }
  step { DispatchOrderOp.run(order: params.order, customer: params.customer) }
end
```

This approach allows you to build readable and testable workflows in your application.

### Running Operations

To run an Operation:

* use the `run` method: &#x20;

```ruby
MyOperation.run
```

* passing params:

```ruby
MyOperation.run(params)
```

* the `then` and `fail` methods, which will dispatch the operation and attach a promise handler: &#x20;

```ruby
MyOperation.run(params)
.then { do_the_next_thing }
.fail { puts 'failed' }
```

### Parameters

Operations can take parameters when they are run. Parameters are described and accessed with the same syntax as Hyperstack Components.

The parameter filter types and options are taken from the [Mutations](https://github.com/cypriss/mutations) gem with the following changes:

* In Hyperstack::Operations all params are declared with the param macro &#x20;
* The type *can* be specified using the `type:` option
* Array and hash types can be shortened to `[]` and `{}`
* Optional params either have the default value associated with the param name or by having the `default` option present
* All other [Mutation filter options](https://github.com/cypriss/mutations/wiki/Filtering-Input) (such as `:min`) will work the same

```ruby
  # required param (does not have a default value)
  param :sku, type: String
  # equivalent Mutation syntax
  # required  { string :sku }

  # optional params (does have a default value)
  param qty: 1, min: 1
  # alternative syntax
  param :qty, default: 1, min: 1
  # equivalent Mutation syntax
  # optional { integer :qty, default: 1, min: 1 }
```

All incoming params are validated against the param declarations, and any errors are posted to the `@errors` instance variable. Extra params are ignored, but missing params unless they have a default value will cause a validation error.

### Defining Execution Steps

Operations may define a sequence of steps to be executed when the operation is run, using the `step`, `failed` and `async` callback macros.

```ruby
class Reset < Hyperstack::Operation
  step { HTTP.post('/logout') }
end
```

* `step`: runs a callback - each step is run in order.
* `failed`: runs a callback if a previous `step` or validation has failed.
* `async`: will be explained below.

```ruby
  step    {  } # do something
  step    {  } # do something else once above step is done
  failed  {  } # do this if anything above has failed
  step    {  } # do a third thing, unless we are on the failed track
  failed  {  } # do this if anything above has failed
```

Together `step` and `failed` form two *railway tracks*. Initially, execution proceeds down the success track until something goes wrong; then execution switches to the failure track starting at the next `failed` statement. Once on the failed track execution continues performing each `failed` callback and skipping any `step` callbacks.

Failure occurs when either an exception is raised, or a Promise fails (more on this in the next section.) The Ruby `fail` keyword can be used as a simple way to switch to the failed track.

Both `step` and `failed` can receive any results delivered by the previous step. If the last step raised an exception (outside a Promise), the failure track would receive the exception object.

The callback may be provided to `step` and `failed` either as a block, a symbol (which will name a method), a proc, a lambda, or an Operation.

```ruby
  step { puts 'hello' }
  step :say_hello
  step -> () { puts 'hello' }
  step Proc.new { puts 'hello' }
  step SayHello # your params will be passed along to SayHello
```

FYI: You can also use the Ruby `next` keyword as expected to leave the current step and move to the next one.

### Promises and Operations

Within the browser, the code does not wait for asynchronous methods (such as HTTP requests or timers) to complete. Operations use Opal's [Promise library](http://opalrb.org/docs/api/v0.10.3/stdlib/Promise.html) to deal with these situations cleanly. A Promise is an object that has three states: It is either still pending, or has been rejected (i.e. failed), or has been successfully resolved. A Promise can have callbacks attached to either the failed or resolved state, and these callbacks will be executed once the Promise is resolved or rejected.

If a `step` or `failed` callback returns a pending Promise then the execution of the operation is suspended, and the Operation will return the Promise to the caller. If there is more track ahead, then execution will resume at the next step when the Promise is resolved. Likewise, if the pending Promise is rejected execution will resume on the next `failed` callback. Because of the way Promises work, the operation steps will all be completed before the resolved state is passed along to the caller so that everything will execute in its original order.

Likewise, the Operation's dispatch occurs when the Promise resolves as well.

The `async` method can be used to override the waiting behavior. If a `step` returns a Promise, and there is an `async` callback further down the track, execution will immediately pick up at the `async`. Any steps in between will still be run when the Promise resolves, but their results will not be passed outside of the operation.

These features make it easy to organize, understand and compose asynchronous code:

```ruby
class AddItemToCart < Hyperstack::Operation
  step { HTTP.get('/inventory/#{params.sku}/qty') }
  # previous step returned a Promise so next step
  # will execute when that Promise resolves
  step { |response| fail if params.qty > response.to_i }
  # once we are sure we have inventory we will dispatch
  # to any listening stores.
end
```

Operations will *always* return a *Promise*. If an Operation has no steps that return a Promise the value of the last step will be wrapped in a resolved Promise. Operations can be easily changed regardless of their internal implementation:

```ruby
class QuickCheckout < Hyperstack::Operation
  param :sku, type: String
  param qty: 1, type: Integer, minimum: 1

  step { AddItemToCart.run(params) }
  step ValidateUserDefaultCC
  step Checkout
end
```

You can also use `Promise#when` if you don't care about the order of Operations

```ruby
class DoABunchOStuff < Hyperstack::Operation
  step { Promise.when(SomeOperation.run, SomeOtherOperation.run) }
  # dispatch when both operations complete
end
```

### Early Exits

Any `step` or `failed` callback, can have an immediate exit from the Operation using the `abort!` and `succeed!` methods. The `abort!` method returns a failed Promise with any supplied parameters. The `succeed!` method does an immediate dispatch and returns a resolved Promise with any supplied parameters. If `succeed!` is used in a `failed` callback, it will override the failed status of the Operation. This is especially useful if you want to dispatch in spite of failures:

```ruby
class Pointless < Hyperstack::Operation
  step { fail }       # go to failure track
  failed { succeed! } # dispatch and exit
end
```

### Validation

An Operation can also have some `validate` callbacks which will run before the first step. This is a handy place to put any additional validations. In the validate method you can add validation type messages using the `add_error` method, and these will be passed along like any other param validation failures.

```ruby
class UpdateProfile < Hyperstack::Operation
  param :first_name, type: String  
  param :last_name, type: String
  param :password, type: String, nils: true
  param :password_confirmation, type: String, nils: true

  validate do
    add_error(
      :password_confirmation,
      :doesnt_match,
      "Your new password and confirmation do not match"
    ) unless params.password == params.confirmation
  end

  # or more simply:

  add_error :password_confirmation, :doesnt_match, "Your new password and confirmation do not match" do
    params.password != params.confirmation
  end

  ...
end
```

If the validate method returns a Promise, then execution will wait until the Promise resolves. If the Promise fails, then the current validation fails.

`abort!` can be called from within `validate` or `add_error` to exit the Operation immediately. Otherwise, all validations will be run and collected together, and the Operation will move onto the `failed` track. If `abort!` is called within an `add_error` callback the error will be added before aborting.

You can also raise an exception directly in validate if appropriate. If a `Hyperstack::AccessViolation` exception is raised the Operation will immediately abort, otherwise just the current validation fails.

To avoid further validations if there are any failures in the basic parameter validations, this can be added

```ruby
  validate { abort! if has_errors? }
```

before the first `validate` or `add_error` call.

### Handling Failed Operations

Because Operations always return a promise, the Promise's `fail` method can be used on the Operation's result to detect failures.

```ruby
QuickCheckout.run(sku: selected_item, qty: selected_qty)
.then do
  # show confirmation
end
.fail do |exception|
  # whatever exception was raised is passed to the fail block
end
```

Failures to validate params result in `Hyperstack::ValidationException` which contains a [Mutations error object](https://github.com/cypriss/mutations#what-about-validation-errors).

```ruby
MyOperation.run.fail do |e|
  if e.is_a? Hyperstack::ValidationException
    e.errors.symbolic     # hash: each key is a parameter that failed validation,
                          # value is a symbol representing the reason
    e.errors.message      # same as symbolic but message is in English
    e.errors.message_list # array of messages where failed parameter is
                          # combined with the message
  end
end
```

### Instance Versus Class Execution Context

Typically the Operation's steps are declared and run in the context of an instance of the Operation. An instance of the Operation is created, runs and is thrown away.

Sometimes it's useful to run a step (or other macro such as `validate`) in the context of the class. This is useful especially for caching values between calls to the Operation. This can be done by defining the steps in the class context, or by providing the option `scope: :class` to the step.

Note that the primary use should be in interfacing to an outside APIs. Application state should not be hidden inside an Operation, and it should be moved to a Store.

```ruby
class GetRandomGithubUser < Hyperstack::Operation
  def self.reload_users
    @promise = HTTP.get("https://api.github.com/users?since=#{rand(500)}").then do |response|
      @users = response.json.collect do |user|
        { name: user[:login], website: user[:html_url], avatar: user[:avatar_url] }
      end
    end
  end
  self.class.step do # as one big step
    return @users.delete_at(rand(@users.length)) unless @users.blank?
    reload_users unless @promise && @promise.pending?
    @promise.then { run }
  end
end
# or
class GetRandomGithubUser < Hyperstack::Operation
  class << self # as 4 steps - whatever you like
    step  { succeed! @users.delete_at(rand(@users.length)) unless @users.blank? }
    step  { succeed! @promise.then { run } if @promise && @promise.pending? }
    step  { self.class.reload_users }
    async { @promise.then { run } }
  end
end
```

An instance of the operation is always created to hold the current parameter values, dispatcher, etc. The first parameter to a class level `step` block or method (if it takes parameters) will always be the instance.

```ruby
class Interesting < Hyperstack::Operation
  param :increment
  param :multiply
  outbound :result
  outbound :total
  step scope: :class { @total ||= 0 }
  step scope: :class { |op| op.params.result = op.params.increment * op.params.multiply }
  step scope: :class { |op| op.params.total = (@total += op.params.result) }
  dispatch
end
```

### The Boot Operation

Hyperstack includes one predefined Operation, `Hyperstack::Application::Boot`, that runs at system initialization. Stores can receive `Hyperstack::Application::Boot` to initialize their state. To reset the state of the application, you can just execute `Hyperstack::Application::Boot`

## Operations can dispatch messages

Hyperstack Operations borrow from the Flux pattern where Operations are dispatchers and Stores are receivers. The choice to use Operations in this depends entirely on the needs and design of your application.

To illustrate this point, here is the simplest Operation:

```ruby
class Reset < Hyperstack::Operation
end
```

To 'Reset' the system you would say

```ruby
  Reset.run
```

Elsewhere your HyperStores can receive the Reset *Dispatch* using the `receives` macro:

```ruby
class Cart < Hyperstack::Store
  receives Reset do
    mutate.items Hash.new { |h, k| h[k] = 0 }
  end
end
```

Note that multiple stores can receive the same *Dispatch*.

> **Note: Flux pattern vs. Hyperstack Operations** Operations serve the role of both Action Creators and Dispatchers described in the Flux architecture. We chose the name `Operation` rather than `Action` or `Mutation` because we feel it best captures all the capabilities of a `Hyperstack::Operation`. Nevertheless, Operations are fully compatible with the Flux Pattern.

### Dispatching With New Parameters

The `dispatch` method sends the `params` object on to any registered receivers. Sometimes it's useful to add additional outbound params before dispatching. Additional params can be declared using the `outbound` macro:

```ruby
class AddItemToCart < Hyperstack::Operation
  param :sku, type: String
  param qty: 1, type: Integer, minimum: 1
  outbound :available

  step { HTTP.get('/inventory/#{params.sku}/qty') }
  step { |response| params.available = response.to_i }
  step { fail if params.qty > params.available }
  dispatch
end
```

### Dispatching messages or invoking steps (or both)?

Facebook is very keen on their Flux architecture where messages are dispatched between receivers. In an extensive and complicated front end application it is easy to see why they are drawn to this architecture as it creates an independence and isolation between Components.

As stated earlier in this documentation, the `step` idea came from Trailblazer, which is an alternative Rails architecture that posits that business functionality should not be kept in the Models, Controllers or Views.

In designing Hyperstack's Isomorphic Operations (which would run on the client and the server), we decided to borrow from the best of both architectures and let Operations work in either way. The decision as to adopt the dispatching or stepping based model is left down to the programmer as determined by their preference or the needs of their application.

## ServerOps can be used to replace boiler-plate APIs

Some Operations simply do not make sense to run on the client as the resources they depend on may not be available on the client. For example, consider an Operation that needs to send an email - there is no mailer on the client so the Operation has to execute from the server.

That said, with our highest goal being developer productivity, it should be as invisible as possible to the developer where the Operation will execute. A developer writing front-end code should be able to invoke a server-side resource (like a mailer) just as easily as they might invoke a client-side resource.

Hyperstack `ServerOps` replace the need for a boiler-plate HTTP API. All serialization and de-serialization of params are handled by Hyperstack. Hyperstack automagically creates the API endpoint needed to invoke a function from the client which executes on the server and returns the results (via a Promise) to the calling client-side code.

### Server Operations

Operations will run on the client or the server. However, some Operations like `ValidateUserDefaultCC` probably need to check information server side and make secure API calls to our credit card processor. Rather than build an API and controller to "validate the user credentials" you just specify that the operation must run on the server by using the `Hyperstack::ServerOp` class.

```ruby
class ValidateUserCredentials < Hyperstack::ServerOp
  param :acting_user
  add_error :acting_user, :no_valid_default_cc, "No valid default credit card" do
    !params.acting_user.has_default_cc?
  end
end
```

A Server Operation will always run on the server even if invoked on the client. When invoked from the client, the ServerOp will receive the `acting_user` param with the current value that your ApplicationController's `acting_user` method returns. Typically the `acting_user` method will return either some User model or nil (if there is no logged in user.) It's up to you to define how `acting_user` is computed, but this is easily done with any of the popular authentication gems. Note that unless you explicitly add `nils: true` to the param declaration, nil will not be accepted.

> **Note regarding Rails Controllers:** Hyperstack is quite flexible and rides along side Rails, without interfering. So you could still have your old controllers, and invoke them the "non-Hyperstack" way by doing say an HTTP.post from the client, etc. Hyperstack adds a new mechanism for communicating between client and server called the Server Operation (which is a subclass of Operation.) A ServerOp has no implication on your existing controllers or code, and if used replaces controllers and client side API calls. HyperModel is built on top of Rails ActiveRecord models, and Server Operations, to keep models in sync across the application. ActiveRecord models that are made public (by moving them to the Hyperstack/models folder) will automatically be synchronized across the clients and the server (subject to permissions given in the Policy classes.) Like Server Operations, HyperModel completely removes the need to build controllers, and client side API code. However all of your current active record models, controllers will continue to work unaffected.

As shown above, you can also define a validation to ensure further that the acting user (with perhaps other parameters) is allowed to perform the operation. In the above case that is the only purpose of the Operation. Another typical use would be to make sure the current acting user has the correct role to perform the operation:

```ruby
  ...
  validate { raise Hyperstack::AccessViolation unless params.acting_user.admin? }
  ...
```

You can bake this kind logic into a superclass:

```ruby
class AdminOnlyOp < Hyperstack::ServerOp
  param :acting_user
  validate { raise Hyperstack::AccessViolation unless params.acting_user.admin? }
end

class DeleteUser < AdminOnlyOp
  param :user
  add_error :user, :cant_delete_user, "Can't delete yourself, or the last admin user" do
    params.user == params.acting_user || (params.user.admin? && AdminUsers.count == 1)
  end
end
```

Because Operations always return a Promise, there is nothing to change on the client to call a Server Operation. A Server Operation will return a Promise that will be resolved (or rejected) when the Operation completes (or fails) on the server.

### Isomorphic Operations

Unless the Operation is a Server Operation, it will run where it was invoked. This can be handy if you have an Operation that needs to run on both the server and the client. For example, an Operation that calculates the customers discount will want to run on the client so the user gets immediate feedback, and then will be run again on the server when the order is submitted as a double check.

### Parameters and ServerOps

You cannot pass an object from the client to the server as a parameter as the server has no way of knowing the state of the object. Hyperstack takes a traditional implementation approach where an id (or some unique identifier) is passed as the parameter and the receiving code finds and created an instance of that object. For example:

```ruby
class IndexBookOp < Hyperstack::ServerOp
  param :book_id
  step { index_book Book.find_by_id params.book_id }
end
```

### Restricting server code to the server

There are valid cases where you will not want your ServerOp's code to be on the client yet still be able to invoke a ServerOp from client or server code. Good reasons for this would include:

* Security concerns where you would not want some part of your code on the client
* Size of code, where there will be unnecessary code downloaded to the client
* Server code using backticks (\`) or the %x{ ... } sequence, both of which are interpreted on the client as escape to generate JS code.

To accomplish this, you wrap the server side implementation of the ServerOp in a `RUBY_ENGINE == 'opal'` test which acts as a compiler directive so that this code is not compiled by Opal.

There are several strategies you can use to apply the RUBY\_ENGINE == 'opal' guard to your code.

```ruby
# strategy 1:  guard blocks of code and declarations that you don't want to compile to the client
class MyServerOp < Hyperstack::ServerOp
  # stuff that is okay to compile on the client
  # ... etc
  unless RUBY_ENGINE == 'opal'
     # other code that should not be compiled to the client...
  end
end
```

```ruby
# strategy 2:  guard individual methods
class MyServerOp < Hyperstack::ServerOp
  # stuff that is okay to compile on the client
  # ... etc
  def my_secret_method
     # do something we don't want to be shown on the client
   end unless RUBY_ENGINE == 'opal'
end
```

```ruby
# strategy 3:  describe class in two pieces
class MyServerOp < Hyperstack::ServerOp; end  # publically declare the operation
# provide the private implementation only on the server
class MyServerOp < Hyperstack::ServerOp
  #
end unless RUBY_ENGINE == 'opal'
```

Here is a fuller example:

```ruby
# app/Hyperstack/operations/list_files.rb
class ListFiles < Hyperstack::ServerOp
  param :acting_user, nils: true
  param pattern: '*'
  step {  run_ls }

  # because backticks are interpreted by the Opal compiler as escape to JS, we
  # have to make sure this does not compile on the client
  def run_ls
    `ls -l #{params.pattern}`
  end unless RUBY_ENGINE == 'opal'
end

# app/Hyperstack/components/app.rb
class App < Hyperstack::Component
  state files: []

  after_mount do
    @pattern = ''
    every(1) { ListFiles.run(pattern: @pattern).then { |files| mutate.files files.split("\n") } }
  end

  render(DIV) do
    INPUT(defaultValue: '')
    .on(:change) { |evt| @pattern = evt.target.value }
    DIV(style: {fontFamily: 'Courier'}) do
      state.files.each do |file|
        DIV { file }
      end
    end
  end
end
```

### Dispatching From Server Operations

You can also broadcast the dispatch from Server Operations to all authorized clients. The `dispatch_to` will determine a list of *channels* to broadcast the dispatch to:

```ruby
class Announcement < Hyperstack::ServerOp
  # no acting_user because we don't want clients to invoke the Operation
  param :message
  param :duration, type: Float, nils: true
  # dispatch to the built-in Hyperstack::Application Channel
  dispatch_to Hyperstack::Application
end

class CurrentAnnouncements < Hyperstack::Store
  state_reader all: [], scope: :class
  receives Announcement do
    mutate.all << params.message
    after(params.duration) { delete params.message } if params.duration
  end
  def self.delete(message)
    mutate.all.delete message
  end
end
```

#### Channels

As seen above broadcasting is done over a *Channel*. Any Ruby class (including Operations) can be used as *class channel*. Any Ruby class that responds to the `id` method can be used as an *instance channel.*

For example, the `User` active record model could be a used as a channel to broadcast to *all* users. Each user instance could also be a separate instance channel that would be used to broadcast to a specific user.

The purpose of having channels is to restrict what gets broadcast to who, therefore typically channels represent *connections* to

* the application (represented by the `Hyperstack::Application` class)
* or some function within the application (like an Operation)
* or some class which is *authenticated* like a User or Administrator,
* instances of those classes,
* or instances of classes in some relationship - like a `team` that a `user` belongs to.

A channel can be created by including the `Hyperstack::Policy::Mixin`, which gives three class methods: `regulate_class_connection` `always_allow_connection` and `regulate_instance_connections`.

For example...

```ruby
class User < ActiveRecord::Base
  include Hyperstack::Policy::Mixin
  regulate_class_connection { self }  
  regulate_instance_connection { self }
end
```

will attach the current acting user to the `User` channel (which is shared with all users) and to that user's private channel.

Both blocks execute with `self` set to the current acting user, but the return value has a different meaning. If `regulate_class_connection` returns any truthy value, then the class level connection will be made on behalf of the acting user. On the other hand, if `regulate_instance_connection` returns an array (possibly nested) or Active Record relationship then an instance connection is made with each object in the list. So, for example, you could add:

```ruby
class User < ActiveRecord::Base
  has_many chat_rooms
  regulate_instance_connection { chat_rooms }
  # we will connect to all the chat room channels we are members of
end
```

To broadcast to all users, the Operation would have

```ruby
  dispatch_to { User } # dispatch to the User class channel
```

or to send an announcement to a specific user

```ruby
class PrivateAnnouncement < Hyperstack::ServerOp
  param :receiver
  param :message
  # dispatch_to can take a block if we need to
  # dynamically compute the channels
  dispatch_to { params.receiver }
end
...
  # somewhere else in the server
  PrivateAnnouncement.run(receiver: User.find_by_login(login), message: 'log off now!')
```

The above will work if `PrivateAnnouncement` is invoked from the server, but usually, some other client would be sending the message so the operation could look like this:

```ruby
class PrivateAnnouncement < Hyperstack::ServerOp
  param :acting_user
  param :receiver
  param :message
  validate { raise Hyperstack::AccessViolation unless params.acting_user.admin? }
  validate { params.receiver = User.find_by_login(receiver) }
  dispatch_to { params.receiver }
end
```

On the client::

```ruby
  PrivateAnnouncement.run(receiver: login_name, message: 'log off now!').fail do
    alert('message could not be sent')
  end
```

and elsewhere in the client code, there would be a component like this:

```ruby
class Alerts < Hyperstack::Component
  include Hyperstack::Store::Mixin
  # for simplicity we are going to merge our store with the component
  state alert_messages: [] scope: :class
  receives PrivateAnnouncement { |params| mutate.alert_messages << params.message }
  render(DIV, class: :alerts) do
    UL do
      state.alert_messages.each do |message|
        LI do
          SPAN { message }
          BUTTON { 'dismiss' }.on(:click) { mutate.alert_messages.delete(message) }
        end
      end
    end
  end
end
```

This will (in only 28 lines of code)

* associate a channel with each logged in user
* invoke the PrivateAnnouncement Operation on the server (remotely from the client)
* validate that there is a logged in user at that client
* validate that we have a non-nil, non-blank receiver and message
* validate that the acting\_user is an admin
* look up the receiver in the database under their login name
* dispatch the parameters back to any clients where the receiver is logged in
* those clients will update their alert\_messages state and
* display the message

The `dispatch_to` callback takes a list of classes, representing *Channels.* The Operation will be dispatched to all clients connected to those Channels. Alternatively `dispatch_to` can take a block, a symbol (indicating a method to call) or a proc. The block, proc or method should return a single Channel, or an array of Channels, which the Operation will be dispatched to. The dispatch\_to callback has access to the params object. For example, we can add an optional `to` param to our Operation, and use this to select which Channel we will broadcast to.

```ruby
class Announcement < Hyperstack::Operation
  param :message
  param :duration
  param to: nil, type: User
  # dispatch to the Users channel only if specified otherwise announcement is application wide
  dispatch_to { params.to || Hyperstack::Application }
end
```

### Defining Connections in ServerOps

The policy methods `always_allow_connection` and `regulate_class_connection` may be used directly in a ServerOp class. This will define a channel dedicated to that class, and will also dispatch to that channel when the Operation completes.

```ruby
class Announcement < Hyperstack::ServerOp
  # all clients will have an Announcement Channel which will
  # receive all dispatches from the Announcement Operation
  always_allow_connection
end
```

```ruby
class AdminOps < Hyperstack::ServerOp
  # subclasses can be invoked from the client if an admin is logged in
  # and all other clients that have a logged in admin will receive the dispatch
  regulate_class_connection { acting_user.admin? }
  param :acting_user
  validate { param.acting_user.admin? }
end
```

### Regulating Dispatches in Policy Classes

Regulations and dispatch lists can be grouped and specified in Policy files, which are by convention kept in the Rails `app/policies` directory.

```ruby
# app/policies/announcement_policy.rb
class AnnouncementPolicy
  always_allow_connection
  dispatch_to { params.acting_user }
end

# app/policies/user_policy.rb
class UserPolicy
  regulate_instance_connection { self }
end
```

### Serialization

If you need to control serialization and deserialization across the wire you can define the following *class* methods:

```ruby
def self.serialize_params(hash)
  # receives param_name -> value pairs
  # return an object ready for to_json
  # default is just return the input hash
end

def self.deserialize_params(object)
  # recieves whatever was returned from serialize_to_server
  # (param_name => value pairs by default)
  # must return a hash of param_name => value pairs
  # by default this returns object
end

def self.serialize_response(object)
  # receives the object ready for to_json
  # by default this returns object
end

def self.deserialize_response(object)
  # receives whatever was returned from serialize_response
  # by default this returns object
end

def self.serialize_dispatch(hash)
  # input is always key - value pairs
  # return an object ready for to_json
  # default just returns the input hash
end

def self.deserialize_dispatch(object)
  # recieves whatever was returned from serialize_to_server
  # (param_name => value pairs by default)
  # must return a hash of param_name => value pairs
  # by default this returns object
end
```

### Accessing the Controller

ServerOps have the ability to receive the "controller" as a param. This is handy for low-level stuff (like login) where you need access to the controller. There is a subclass of ServerOp called ControllerOp that simply declares this param and will delegate any controller methods to the controller param. So within a `ControllerOp` if you say `session` you will get the session object from the controller.

Here is a sample of the SignIn operation using the Devise Gem:

```ruby
class SignIn < Hyperstack::ControllerOp
  param :email
  inbound :password
  add_error(:email, :does_not_exist, 'that login does not exist') { !(@user = User.find_by_email(params.email)) }
  add_error(:password, :is_incorrect, 'password is incorrect') { !@user.valid_password?(params.password)  }
 # no longer have to do this step { params.password = nil }
  step { sign_in(:user, @user)  }
end
```

In the code above there is another parameter type in ServerOps, called inbound, which will not get dispatched.

### Broadcasting to the current\_session

Let's say you would like to be able to broadcast to the current session. For example, after the user signs in we want to broadcast to all the browser windows the user happens to have open so that they can update.

For this, we have a `current_session` method in the `ControllerOp` that you can dispatch to.

```ruby
class SignIn < Hyperstack::ControllerOp
  param :email
  inbound :password
  add_error(:email, :does_not_exist, 'that login does not exist') { !(@user = User.find_by_email(params.email)) }
  add_error(:password, :is_incorrect, 'password is incorrect') { !@user.valid_password?(params.password)  }
  step { sign_in(:user, @user)  }
  dispatch_to { current_session }
end
```

The Session channel is special so to attach to the application to it you would say in the top level component:

```ruby
class App < Hyperstack::Component
  after_mount :connect_session
end
```

## Additional information

### Operation Capabilities

Operations have the following capabilities:

* Can easily be chained because they always return Promises
* declare both their parameters and what they will dispatch
* Parameters can be validated and type checked
* Can run remotely on the server
* Can be dispatched from the server to all authorized clients.
* Can hold their own state data when appropriate
* Operations also serves as the bridge between client and server
* An operation can run on the client or the server and can be invoked remotely.

**Use Operations as you choose**. This architecture is descriptive but not prescriptive. Depending on the needs of your application and your overall thoughts on architecture, you may need a little or a lot of the functionality provided by Operations. If you chose, you could keep all your business logic in your Models, Stores or Components - we suggest that it is better application design not to do this, but the choice is yours.

### Background

The design of Hyperstack's Operations have been inspired by three concepts: [Trailblazer Operations](http://trailblazer.to/gems/operation/2.0/) (for encapsulating business logic in `steps`), the [Flux pattern](https://facebook.github.io/flux/) (for dispatchers and receivers), and the [Mutation Gem](https://github.com/cypriss/mutations) (for validating params).

### Hyperstack Operations compared to Flux

| Flux                | Hyperstack                                        |
| ------------------- | ------------------------------------------------- |
| Action              | Hyperstack::Operation subclass                    |
| ActionCreator       | `Hyperstack::Operation.step/failed/async` methods |
| Action Data         | Hyperstack::Operation parameters                  |
| Dispatcher          | `Hyperstack::Operation#dispatch` method           |
| Registering a Store | `Store.receives`                                  |


# Policies

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true) **Your data is protected by Hyperstack's policy mechanism. Policies regulate Create, Read/Broadcast, Update and Delete access based on the browsers logged in user. You define in one set of files what data can be seen by who, and who can update the database**

## This Page Under Construction

Access to your Isomorphic Models is controlled by *Policies* that describe how the current *acting\_user* and *channels* may access your Models.

Each browser session has an *acting\_user* (which may be nil) and you will define `create`, `update`, and `destroy` policies giving (or denying) the `acting_user` the ability to do these operations.

Read and *broadcast* access is defined based on *channels* which are connected based again on the current `acting_user`. Read access is initiated when a specific browser tries to read a record attribute, and broadcasts are initiated whenever a model changes.

An application can have several channels and each channel and each active record model can have different policies to determine which attributes are sent when a record changes.

For example a Todo application might have an *instance* of a channel for each currently logged in user; an instance of a channel for each team if that team has one or more logged in users; and a general `AdminUser` channel shared by all administrators that are logged in.

Lets say a specific `Todo` changes, which is part of team id 123's Todo list, and users 7 and 8 who are members of that team are currently logged in as well as two of the `AdminUsers`.

When the `Todo` changes we want all the attributes of the `Todo` broadcast on team 123's channel, as well on the `AdminUser`'s channel. Now lets say User 7 sends User 8 a private message, adding a new record to the `Message` model. This update should only be sent to user 7 and user 8's private channels, as well as to the AdminUser channel.

We can define all these policies by creating the following classes:

```ruby
class UserPolicy # defines policies for the User class
  # The regulate_instance_connections method enables instances of the User
  # class to be treated as a channel.  

  # The policy is defined by a block that is executed in the context of the
  # current acting_user.

  # For our User instance connection the policy is that there must be a
  # logged-in user, and the connection is made to that user:
  regulate_instance_connections { self }
  # If there is no logged in user self will be nil, and no connection will be
  # made.
end

class TeamPolicy # defines policies for the Team class  
  # Users can only connect to Teams that they belong to
  regulate_instance_connections { teams }
end

class AdminUserPolicy
  # All AdminUsers share the same connection so we setup a class wide
  # connection available to any users who are admins.
  regulate_class_connection { admin? }

  # The AdminUser channel will receive all attributes
  # of all records, unless the attribute is named :password
  regulate_all_broadcasts do |policy|
    policy.send_all_but(:password)
  end
end

class TodoPolicy
  # Policies can be established for models that are not channels as well.

  # The regulate_broadcast method will describe what attributes to send
  # when a Todo model changes.  

  # The blocks of broadcast policies run in the context of the changed model
  # so we have access to all the models methods.  In this case Todo
  # belongs to a Team through the 'team' relationship.
  regulate_broadcast do |policy|
    # send all Todo attributes to the todo's team channel
    policy.send_all.to(team)
  end
end

class MessagePolicy
  # Broadcast policies can be arbitrarily complex.  In this case we
  # want to broadcast the entire message to the sender and the
  # recipient's instance channels.  
  # In addition if the message is not private, then we want to send to all
  # the team instance channels that are shared between the sender and
  # recipient's teams.
  regulate_broadcast do |policy|
    policy.send_all.to(sender, recipient)
    policy.send_all.to(sender.teams.merge(recipient.teams)) unless private?
  end
end
```

Before we begin using these channels and policies we need to first define the Reactive-Record `acting_user` method in our ApplicationController:

```ruby
class ApplicationController < ActionController::Base
  def acting_user
    # The acting_user method should return nil, or some object that corresponds to a
    # logged in user.  Specifics will depend on your application and whatever other
    # authentication mechanisms you are using.
    @acting_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id])
    end
  end
end
```

Note that `acting_user` is also used by ReactiveRecord's permission system.

Our entire set of policies is defined in 29 lines of code of which 8 actually execute the policies. Our existing classes form the foundation, and we simply add Hyperloop specific policy directives. Pretty sweet huh?

### Details

Hyperloop uses *Policies* to *regulate* what *connections* are opened between clients and the server and what data is distributed over those connections.

Connections are made on *channels* of data flowing between the server and a number of clients. Each channel is associated with either a class or an instance of a class. Typically the channel class represents an entity (or is associated with an entity) that can be authenticated like a `User`, an `AdminUser`, or a `Team` of users. A channel associated with the class itself broadcasts data that is received by any member of that class. A channel associated with an instance is for data that is available only to that specific instance.

As Models on the server change (i.e. created, updated, or destroyed) the changes are broadcast over open channels. What specific attributes are sent (if any) is determined by broadcast policies.

Broadcast policies can be associated with Models. As the Model changes the broadcast policy will regulate what attributes of the changed model will be sent over which channels.

Broadcast policies can also be associated with a channel and will regulate *all* model changes over specific channels. In other words this is just a convenient way to associate a common policy with *all* Models.

Note that Models that are associated with channels can also broadcast their changes on the same or different channels.

#### Defining Policies and Policy Classes

The best way to define policies is to use a *Policy Class*. A policy class has the same class name as the class it is regulating, with `Policy` added to the end. Policy classes are compatible with `Pundit`, and you can add regular pundit policies as well.

Policies are defined using four methods:

* `regulate_class_connection` controls connections to the class channels,
* `regulate_instance_connections` controls connections to instance channels,
* `regulate_broadcast` controls what data will be sent when a model or object changes and,
* `regulate_all_broadcasts` controls what data will be sent of some channels when any model changes.

In addition `always_allow_connection` is short hand for `regulate_class_connection { true }`

A policy class can be defined for which there is no regulated class. This is useful for application wide connections, which are typically open even if no one is logged in:

```ruby
#app/policies/application.rb
class ApplicationPolicy
  regulate_class_connection { true }
end
```

Note that by default policy classes go in the `app/policies` directory. Hyperloop will require all the files in this directory.

If you wish, you can also add policies directly in your Models by including the `Hyperloop::PolicyMethods` module in your model. You can then use the `regulate_class_connection`, `regulate_instance_connections`, `regulate_all_broadcasts` and `regulate_broadcast` methods directly in the model.

```ruby
class User < ActiveRecord::Base
  include Hyperloop::PolicyMethods
  regulate_class_connection ...
  regulate_instance_connections ...
  regulate_all_broadcasts ...  
  regulate_broadcast ...
end
```

Normally the policy methods are regulating the class with the prefix as the policy, but you can override this by providing specific class names to the policy method. This allows you to group several different class policies together, and to reuse policies:

```ruby
class ApplicationPolicy
  regulate_connection { ... }  # Application is assumed
  regulate_class_connection(User) { ... }
  # regulate_class_connection, regulate_instance_connections and
  # regulate_all_broadcasts can take a list of channels.
  regulate_all_broadcasts(User, Application)
  # regulate_broadcast takes a list of object classes which
  # may also be channels.
  regulate_broadcast(Todo, Message, User) { ... }
end
```

#### Channels and connection policies

Any ruby class that has a connection policy is a Hyperloop channel. The fully scoped name of the class becomes the root of the channel name.

The purpose of having channels is to restrict what gets broadcast when models change, therefore typically channels represent *connections* to

* the application, or some function within the application
* or some class which is *authenticated* like a User or Administrator,
* instances of those classes,
* or instances of related classes.

So a channel that is connected to the User class would get information readable by any logged-in user, while a channel that is connected to a specific User instance would get information readable by that specific user.

The `regulate_class_connection` takes a block that will execute in the context of the current acting\_user (which may be nil), and if the block returns any truthy value, the connection will be made.

The `regulate_instance_connections` likewise takes a block that is executed in the context of the current acting\_user. The block may do one of following:

* raise an error meaning the connection cannot be made
* return a falsy value also meaning the connection cannot be made
* return a single object meaning the connection can be made to that object
* return a enumerable of objects meaning the connection can made to any member of the enumerable

Note that the object (or objects) returned are expected to be of the same class as the regulated policy.

```ruby
# Create a class connection only if the acting_user is non-nil (i.e. logged in:)
regulate_class_connection { self }
# Always open the connection:
regulate_class_connection { true }
# Which can be shortened to:
always_allow_connection
# Create a class level connection if the acting_user is an admin:
regulate_class_connection { admin? }
# Create an instance connection for the current user:
regulate_instance_connections { self }
# Create an instance connection for the current user if the user is an admin:
regulate_instance_connections { self if admin? }
# create an instance_connection to the users' group
regulate_instance_connections { group }
# create an instance connection for any team the user belongs to
regulate_instance_connections { teams }
```

#### Class Names Instances and IDs

While establishing connections, classes are represented as their fully scoped name, and instances are represented as the class name plus the result of calling `id` on the instance.

Typically connections are made to ActiveRecord models, and if those are in the `app/hyperloop/models` folder everything will work fine.

## Acting User

Hyperloop looks for an `acting_user` method typically defined in the ApplicationController and would normally pick up the current session user, and return an appropriate object.

```ruby
class ApplicationController < ActiveController::Base
  def acting_user
    @acting_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id])
    end
  end
end
```

#### Automatic Connection

Connections to channels available to the current `acting_user` are automatically made on the initial page load. This behavior can be turned off with the `auto_connect` option.

```ruby
class TeamPolicy
  # Allow current users to establish connections to any teams they are
  # members of, but disable_auto_connect
  regulate_instance_connections(auto_connect: false) { teams }
end
```

Its important to consider turning off automatic connections for cases like the above where the user is likely to be a member of many teams. Typically the client application will want to dynamically determine which specific teams to connect to given the current state of the application.

### Manually Connecting to Channels

Normally the client will automatically connect to the available channels when a page loads, but you can also manually connect on the client in response to some user action like logging in, or the user deciding to display a specific team status on their dashboard.

To manually connect a client use the `Hyperloop.connect` method.

The `connect` method takes any number of arguments each of which is either a class, an object, a String or Array.

If the argument is a class then the connection will be made to the matching class channel on the server.

```ruby
# connect the client to the AdminUser class channel
Hyperloop.connect(AdminUser)
# if the connection is successful the client will begin getting updates on the
# AdminUser class channel
```

If the argument is an object then a connection will be made to the matching object on the server.

```ruby
# assume current_user is an instance of class User
Hyperloop.connect(current_user)
# current_user.id is used to establish which User instance to connect to on the
# server
```

The argument can also be a string, which matches the name of a class on the server

```ruby
Hyperloop.connect('AdminUser')
# same as AdminUser class
```

or the argument can be an array with a string and the id:

```ruby
Hyperloop.connect(['User', current_user.id])
# same as saying current_user
```

You can make several connections at once as well:

```ruby
Hyperloop.connect(AdminUser, current_user)
```

Finally falsy values are ignored.

You can also send `connect` directly to ActiveRecord models:

```ruby
AdminUser.connect    # same as Hyperloop.connect(AdminUser)
current_user.connect # same as Hyperloop.connect(current_user)
```

#### Connection Sequence Summary

For class connections:

1. The client calls `Hyperloop.connect`.
2. Hyperloop sends the channel name to the server.
3. Hyperloop has its own controller which will determine the `acting_user`,
4. and call the channel's `regulate_class_connection` method.
5. If `regulate_class_connection` returns a truthy value then the connection is made,
6. otherwise a 500 error is returned.

For instance connections:

1. The process is the same but the channel name and id are sent to the server. &#x20;
2. The Hyperloop controller will do a `find` of the id passed to get the instance,
3. and if successful `regulate_instance_connections` is called,
4. which must return an either the same instance, or an enumerable with that instance as a member.
5. Otherwise a 500 error is returned.

Note that the same sequence is used for auto connections and manually invoked connections.

#### Disconnecting

Calling `Hyperloop.disconnect(channel)` or `channel.disconnect!` will disconnect from the channel.

## Broadcasting and Broadcast Policies

Broadcast policies can be defined for channels using the `regulate_all_broadcasts` method, and for individual objects (typically ActiveRecord models) using the `regulate_broadcast` method. A `regulate_all_broadcasts` policy is essentially a `regulate_broadcast` that will be run for every record that changes in the system.

After an ActiveRecord Model change is committed, all active class channels run their channel broadcast policies, and then the instance broadcast policy associated with the changing Model is run. So for any change there may be multiple channel broadcast policies involved, but only one (at most) regulate\_broadcast.

The result is that each channel may get a filtered copy of the record which is broadcast on that channel.

The purpose of the policies then is to determine which channel sees what. Each broadcast policy receives the instance of the policy which responds to the following methods

* `send_all`: send all the attributes of the record.
* `send_only`: send only the listed attributes of the record.
* `send_all_but`: send all the attributes except the ones listed.

The result of the `send...` method is then directed to the set of channels using the `to` method:

```ruby
policy.send_all_but(:password).to(AdminUser)
```

Within channel broadcast policies the channel is assumed to be the channel in question:

```ruby
class AdminUserPolicy
  regulate_all_broadcasts do |policy|
    policy.send_all_but(:password) #.to(AdminUser) is not needed.
  end
end
```

The `to` method can take any number of arguments:

* a class naming a channel,
* an object that is instance channel,
* an ActiveRecord collection,
* any falsy value which will be ignored,
* or an array that will be flattened and merged with the other arguments.

The broadcast policy executes in the context of the model that has just changed, so the policy can use all the methods of that model, especially relationships. For example:

```ruby
class Message < ActiveRecord::Base
  belongs_to :sender, class: "User"
  belongs_to :recipient, class: "User"
end

class MessagePolicy
  regulate_broadcast do |policy|
    # send all attributes to both the sender, and recipient User instance channels
    policy.send_all.to(sender, recipient)
    # send all attributes to intersection
    policy.send_all.to(sender.teams.merge(recipient.teams)) unless private?
  end
end
```

It is possible that the same channel may be sent a record from different policies, in this case the minimum set of attributes will be sent regardless of the order of the send operations. For example:

```ruby
policy.send_all_but(:password).to(MyChannel)
# ... later
policy.send_all.to(MyChannel)
# MyChannel gets everything but the password
```

or even

```ruby
policy.send_only(:foo, :bar).to(MyChannel)
policy.send_only(:baz).to(MyChannel)
# MyChannel gets nothing
```

Keep in mind that the broadcast policies are sent a copy of the policy object so you can use helper methods in your policies. Also you can add policy specific methods to your models using `class_eval` thus keeping policy logic out of your models.

So we could for example we can rewrite the above MessagePolicy like this:

```ruby
class MessagePolicy
  Message.class_eval do
    scope :teams_for_policy, -> () { sender.teams.merge(recipient.teams) }
  end
  def teams  # the obj method returns the instance being regulated
    [obj.sender, obj.recipient, !obj.private? && obj.teams_for_policy]
  end
  regulate_broadcast { |policy| policy.send_all.to(policy.teams) }
end
```

## Browser Initiated Change policies

To allow code in the browser to create, update or destroy a model, there must be a change access policy defined for that operation.

Each change access policy executes a block in the context of the record that will be accessed. The current value of `acting_user` is also defined for the life of the block.

If the block returns a truthy value access will be allowed, otherwise if the block returns a falsy value or raises an exception, access will be denied.

In the below examples we assume that your user model responds to `admin?` but this is not built into Hyperloop.

```ruby
class TodoPolicy
  # allow creation to any logged in user
  allow_create { acting_user }
  # only allow the owner, author any any admin to update a todo
  allow_update { acting_user == owner || acting_user == author || acting_user.admin? }
  # don't allow Todo's to be destroyed
  # this is the default behavior so its not actually needed
  allow_destroy { false }
end
```

There are several variants of the access policy method:

```ruby
class ConfigDataPolicy
  allow_change(on: [:create, :update, :destroy]) { acting_user.admin? }
  # which can be shortened to:
  allow_change { acting_user.admin? }
end
```

```ruby
class ApplicationPolicy
  # do any thing to all models unless we are in production!  Be careful!
  allow_change(to: :all) { true } unless Rails.env.production?
  # and always allow admins to destroy models globally:
  allow_change(to: :all, on: :destroy) { acting_user.admin? }
  # which is the same as saying:
  allow_destroy(to: :all) { acting_user.admin? }
  # you can create model specific policies in the Application Policy as well.
  # Here we allow the author of a message to destroy the message within 5
  # minutes of creation.
  allow_destroy(to: Message) do
    return true if acting_user == author && created_at > 5.minutes.ago
    return true if acting_user.admin?
  end
end
```

Note that there is no `allow_read` method. Read access is granted if this browser would have the attribute broadcast to it.

## Method Summary and Name Space Conflicts

Policy classes (and the Hyperloop::PolicyMethods module) define the following class methods:

* `regulate_connection`
* `regulate_all_broadcasts`
* `regulate_broadcast`

As well as the following instance methods:

* `send_all`
* `send_all_but`
* `send_only`
* `obj`

To avoid name space conflicts with your classes, Hyperloop policy classes (and the Hyperloop::PolicyMethods module) maintain class and instance `attr_accessor`s named `synchromesh_internal_policy_object`. The above methods call methods of the same name in the appropriate internal policy object.

You may thus freely redefine of the class and instance methods if you have name space conflicts

```ruby
class ProductionCenterPolicy < MyPolicyClass
  # MyPolicyClass already defines our version of obj
  # so we will call it 'this'
  def this
    synchromesh_internal_policy_object.obj
  end
  ...
end
```

TODO: rewrite the following:

First as you say to explicitly send stuff to all applicants. Policies work "backwards" to how you might think in a controller. In a controller you might check something like acting\_user.chatrooms.include?(message.chatroom) whereas Hyperloop starts from the other end, it'll effectively do something like this message.chatroom.participants.include?(acting\_user). Your job in a policy is to start with the actual record, then traverse the relationships to return the user or users it belongs to. Think in terms of "I have a thing, who are all the people who are allowed to see it?". Now that may or may not work in your case. If you have anonymous accounts for applicants but they all still have user records and thus IDs then it will work — job\_posting.hiring\_manager.applicants. But if applicants didn't have any record then you couldn't use this style of "instance channel policy". Instance == ids == non-public. So if something is public you can use a class channel. send\_all.to(Applicant). Finally you can have many channels or just a few. In our app I've gone with a user instance channel, and a user class channel. That's just what works for my mental model. But you could have other instance and class channels to make dividing things up easier, your scope chains shorter, etc. Hopefully you can look at the docs now and see instance, class, channel, broadcast, etc. and come up with a way that works for you. Mitch's snippet looks good, I just tried to give some surrounding color.

The policy send all bit is about once you've got a record/records, are you allowed to see it and what attributes are you allowed to see (in that case all, but you can permit a subset). The regulate bit is about what relations are you allowed to access. It may seem redundant as without regulations event if you loaded the relation you still wouldn't be able see any of the record attributes without a policy. So even without regulations there's no risk of exposing private information. BUT what would leak is lists IDs and counts. A count doesn't instantiate any records so there's nothing to run a policy on. Leaking counts and IDs is metadata that may or may not be sensitive, aka you wouldn't want an insurance company to be able to do patient.diseases.count. And if you're using UUIDs so you don't sequentially leak all of your public pages, again you'd want a regulation to protect that. They can also prevent denial of service attacks loading big expensive relations. So, broadcast policies are about who can see the attributes of an individual record (or collection but it's still run on each record individually). Regulations are about preventing business data leakage.

from Mitch...

These work very similar to pundit, and by design you can even mix pundit and hyperloop policies. Here is an example pundit policy from the pundit tutorial:

```ruby
# app/policies/article_policy.rb
class ArticlePolicy < ApplicationPolicy
  def index?
    true
  end

  def create?
    user.present?
  end

  def update?
    return true if user.present? && user == article.user
  end

  def destroy?
    return true if user.present? && user == article.user
  end

  private

    def article
      record
    end
end
```

```ruby
class ArticlePolicy < ApplicationPolicy
  # def index?
  #   true
  # end

  # read policies are defined as part of broadcast policies.  (if you can receive
  # it in a broadcast then you can read it)
  # There is no controller in hyperloop so broadcast/read policies
  # are defined in terms of what data is sent to what channel

  regulate_broadcast do |policy|
    policy.send_all.to Application
  end

  # def create?
  #   user.present? <- create is okay if user is not nil
  # end

  allow_create { acting_user }  # <- create is okay if acting_user is  not nil

  # def update?
  #   return true if user.present? && user == article.user
  # end

  # only difference is hyperloop makes it easier by
  # 1) running the block with self == the the record
  # 2) adding the acting_user method to self
  # 3) treating exceptions as the same as nil

  allow_update { acting_user == user }

  # def destroy?
  #   return true if user.present? && user == article.user
  # end

  allow_destroy { acting_user == user }

  # the above two regulations are the same and so can be dried up like this:

  allow_change(on: [:update, :destroy]) { acting_user == user }

  # private
  #
  #   def article
  #     record
  #   end
end
```

without comments....

```
class ArticlePolicy < ApplicationPolicy
  regulate_broadcast { |policy| policy.send_all.to Application }

  allow_create { acting_user }  # <- create is okay if acting_user is  not nil

  allow_change(on: [:update, :destroy]) { acting_user == user }
end
```

BTW what if you want to restrict what data is broadcast? In Hyperloop you just update the regulation. In pundit you may have to edit both the index controller method and Policy class.


# Internationalization

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true) HyperI18n seamlessly brings Rails I18n into your Hyperstack application.

## This Page Under Construction

## Installation and Setup

**TODO these steps are wrong**

1. Add `gem 'hyper-i18n', git: 'https://github.com/ruby-Hyperstack/hyper-i18n.git'` to your `Gemfile`
2. Install the Gem: `bundle install`
3. Add `require 'hyper-i18n'` to your components manifest

### Usage

Hyper-I18n brings in the standard ActiveSupport API.

#### ActiveRecord Models

The methods `Model.model_name.human` and `Model.human_attribute_name` are available:

```yaml
# config/locales/models/en.yml
en:
  activerecord:
    models:
      user: 'Customer'
    attributes:
      name: 'Name'
```

```ruby
User.model_name.human
# 'Customer'

User.human_attribute_name(:name)
# 'Name'
```

#### Views

Hyper-I18n makes available the method `t` to components, just as ActiveSupport does for views. It also implements the same lazy-loading pattern, so if you name space your locale file the same as your components, it will just work:

```yaml
# config/locales/views/en.yml
en:
  users:
    show:
      title: 'Customer View'
```

```ruby
module Users
  class Show < Hyperstack::Component
    render do
      H1 { t(:title) }
    end
  end
end

# <h1>Customer View</h1>
```

### Server Rendering

HyperI18n is fully compatible with server rendering! All translations are also sent to the client, so as to bypass fetching/rendering again on the client.


# Development Tools, Workflow and Procedures


# Debugging

Debugging any UI code is difficult. Hyperstack's declarative approach, and lack of redundant boilerplate helps a lot. Simply having 1/4 the code base to deliver the same functionality is going to make things easier.

However all that said, **Debugging UI Code is Difficult.** The UI's main job is to deal with events coming from multiple directions and unpredictable sources, this makes tracking down failures difficult as timing can become an issue.

Here are few tips to go along with the other tools in this section (HyperSpec and HyperTrace) to make your life a bit easier.

## JavaScript Console

At any time during program execution you can breakout into the JavaScript console by simply adding the debugger keyword to your Ruby code.

If you have source maps turned on you will then be able to see your ruby code (and the compiled JavaScript code) and set browser breakpoints, examine values and continue execution.

> Important Note: The Opal compiler will not handle the `debugger` keyword at the end of blocks, method definitions, or begin..end statements.
>
> ```ruby
> def buggy_method
>   ...
>   debugger # this will break add any expression on the next line to fix
> end
> ```

You can also inspect Ruby objects from the JavaScript console. The mapping between the Javascript and Ruby is fairly easy to follow thanks to the great Opal team.

Here are some tips: <https://dev.mikamai.com/2014/11/19/3-tricks-to-debug-opal-code-from-your-browser/>

## The `puts` method is your friend

Anywhere in your HyperReact code you can simply puts any\_value which will display the contents of the value in the browser console. This can help you understand React program flow as well as how data changes over time.

```ruby
class Thing < Hyperstack::Component
  param initial_mode: 12

  before_mount do
    state.mode! params.initial_mode
    puts "before_mount params.initial_mode=#{params.initial_mode}"
  end

  after_mount do
    @timer = every(60) { force_update! }
    puts "after_mount params.initial_mode=#{params.initial_mode}"
  end

  render do
    div(class: :time) do
      puts "render params.initial_mode=#{params.initial_mode}"
      puts "render state.mode=#{state.mode}"
      ...
      end.on(:change) do |e|
        state.mode!(e.target.value.to_i)
        puts "on:change e.target.value.to_i=#{e.target.value.to_i}"
        puts "on:change (too high) state.mode=#{state.mode}" if state.mode > 100
      end
    end
  end
end
```

## HyperTrace

Sometimes popping in a trace can reveal a lot about what is going on. [HyperTrace](/development-workflow/hyper-trace) wraps your selected method calls in a dump of incoming parameters, instance variable state, and return values. You can also setup conditional breakpoints. So keep HyperTrace handy in your tool belt.

## HyperSpec

IMHO the best debugging tool is a spec. As soon as you start creating a new feature, or find a bug, start writing a spec. Once you can reproduce the problem by running a spec, you are 90% of the way to fixing the problem, and you will have another spec to add to your tests, making your app more robust. [HyperSpec](/development-workflow/hyper-spec) extends RSpec so that can control and interrogate the client from within your specs, using Ruby code.


# HyperTrace

![](https://github.com/hyperstack-org/hyperstack/blob/edge/docs/wip.png?raw=true) HyperTrace provides a simple way to log information to the Javascript console. You get a real time display of the parameters being passed to the traced methods, the state of their instance variables, and the return values. You can also set conditional breakpoints so you can stop execution and dig deeper from the Javascript console.

## This Page Under Construction


# HyperSpec

## Adding client side testing to RSpec

The `hyper-spec` gem supports the Hyperstack goals of programmer productivity and seamless web development by allowing testing to be done with minimal concern for the client-server interface.

The `hyper-spec` gem adds functionality to the `rspec`, `capybara`, `timecop` and `pry` gems allowing you to do the following:

* write component and integration tests using the rspec syntax and helpers
* write specs that run on both the client and server
* evaluate client side ruby expressions from within specs and while using `pry`
* share data between the client and server within your specs
* control and synchronize time on the client and the server

HyperSpec can be used standalone, but if used as part of a Hyperstack application it allows straight forward testing of Hyperstack Components and your ActiveRecord Models.

So for example here is part of a simple unit test of a TodoIndex component:

```ruby
it "will update the TodoIndex", js: true do
  # mounts the TodoIndex component (client side)
  mount 'TodoIndex'
  # Todo is an ActiveRecord Model
  # create a new Todo on the server (we could use FactoryBot of course)
  todo_1 = Todo.create(title: 'this todo created on the server')
  # verify that UI got updated
  expect(find('.ToDoItem-Text').text).to eq todo_1.title
  # verify that the count of Todos on the client side DB matches the server
  expect { Todo.count }.on_client_to eq Todo.count
  # now create another Todo on the client
  new_todo_title = 'this todo created on the client'
  # note that local variables are copied from the server to the client
  on_client { Todo.create(title: new_todo_title) }
  # the Todo should now be reflected on the server
  expect(Todo.last.title).to eq new_todo_title
end
```

When using HyperSpec all the specs execute on the server side, but they may also interrogate the state of the UI as well as the state of any of the client side objects. The specs can execute any valid Ruby code client side to create new test objects as well as do white box testing. This keeps the logic of your specs in one place.


# Installation

Add `gem 'hyper-spec'` to your Gemfile in the usual way.\
Typically in a Rails app you will add this in the test section of your Gemfile:

```ruby
group :test do
  gem 'hyper-spec', '~> 1.0.alpha1.0'
end
```

Make sure to `bundle install`.

HyperSpec is integrated with the `pry` gem for debugging, so it is recommended to add the `pry` gem as well.

HyperSpec will also use the `timecop` gem if present to allow you to control and synchronize time on the server and the client.

A typical spec\_helper file when using HyperSpec will look like this:

```ruby
# spec_helper.rb
require 'hyper-spec'
require 'pry'  # optional

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path('../test_app/config/environment', __FILE__)

require 'rspec/rails'
require 'timecop' # optional

# any other rspec configuration you need
# note HyperSpec will include chrome driver for providing the client
# run time environment
```

To load the webdriver and client environment your spec should have the `:js` flag set:

```ruby
# the js flag can be set on the entire group of specs, or a context
describe 'some hyper-specs', :js do
  ...
end

# or for an individual spec
  it 'an individual hyper-spec', :js do
    ...
  end
```


# Tutorial

For this quick tutorial lets assume you have an existing Rails app that already uses RSpec to which you have added a first Hyperstack component to try things out.

For your trial, you have created a very simple component that shows the number of orders shipped by your companies website:

```ruby
class OrdersShipped < HyperComponent
  def format_number(number)
    number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
  end

  render(DIV, class: 'orders-shipped') do
    format_number Order.shipped.count
  end
end
```

> Note that styling can be taken care of in the usual way by providing styles for the `orders-shipped` css class. All we care about here is the *function* of the component.

Meanwhile `Order` is an ActiveRecord Model that would look something like this:

```ruby
class Order < ApplicationRecord
  ...
  scope :shipped, -> () { where(status: :shipped) }
  ...
end
```

> Note that when using ActiveRecord models in your specs you will need to add the appropriate database setup and cleaner methods like you would for any specs used with ActiveRecord. We assume here that as each spec starts there are no records in the database

The `OrdersShipped` component can be mounted on any page of your site, and assuming the proper policy permissions are provided it will show the total orders shipped, and will dynamically increase in realtime.

A partial spec for this component might look like this:

```ruby
require 'spec_helper'

describe 'OrdersShipped', :js do
  it 'dynamically displays the orders shipped' do
    mount 'OrdersShipped'
    expect(find('div.orders-shipped')).to have_content(0)
    Order.create(status: :shipped)
    expect(find('div.orders-shipped')).to have_content(1)
    Order.last.destroy
    expect(find('div.orders-shipped')).to have_content(0)
  end

  it '#format method' do
    on_client { @comp = OrdersShipped.new }
    ['1,234,567', '123', '1,234'].each do |n|
      expect { @comp.format_number(n.gsub(',','').to_i) }
        .on_client_to eq(n)
    end
  end
end
```

If you are familiar with Capybara then the first spec should look similar to an integration spec. The difference is instead of visiting a page, we `mount` the `OrdersShipped` component on a blank page that hyper-spec will set up for us. This lets us unit test components outside of any application specific view logic.

> Note that like Capybara we indicate that a client environment should be set up by adding the :js tag.

Once mounted we can use Capybara finders and matchers to check if our content is as expected. Because we are running on the server we can easily add and delete orders, and check the response on the UI.

The second spec shows how we can do some white box unit testing of our component. Instead of mounting the component we just create a new instance which will be invisible since it was not mounted. For this we use the `on_client` method.

The `on_client` method takes a block, and will compile that block using Opal, and execute it on the client. In this case we simply create a new `OrderShipped` instance, and assign it to an instance variable, which as you will see will continue to be available to us later in the spec.

> Note, if you are an RSpec purist, you would probably prefer to see something like `let` be used here instead of an instance variable. Shall we say its on the todo list.

Now that we have our test component setup we can test its `format_number` method. To do this we put the test expression in a block followed by `on_client_to`. Again the block will be compiled using Opal, executed on the client, and the result will be returned to the expectation.

Notice that the server side variable `n` can be read (but not written) within the client block. All local variables, memoized variables, and instance variables can can be read in the client block as long as they represent objects that can be sensibly marshalled and unmarshalled.

This has covered the basics of Hyperspec - in summary:

* The `js` tag  indicates the spec will be using a client environment.
* `mount`: Mount a component on a blank page.  This replaces the `visit` method

  for unit testing components.
* `on_client`:  Execute Ruby code on the client (and return the result).
* `on_client_to`: Execute the expectation block on the client, and then check

  the expectation (on the server.)
* Instance variables retain their values between client execution blocks.
* All variables accessible to the spec are copied to the client if possible.

There are many other features such as dealing with promises, passing data to and from a mounted component, using the `Timecop` gem, and working with a `pry` session. So read on.


# Methods and Features

## HyperSpec Methods and Features

### Expectation Helpers

These can be used any where within your specs:

* [`on_client`](/development-workflow/hyper-spec/03-methods-and-features#the-on_client-method) - executes code on the client
* [`isomorphic`](/development-workflow/hyper-spec/03-methods-and-features#the-isomorphic-method) - executes code on the client *and* the server
* [`mount`](/development-workflow/hyper-spec/03-methods-and-features#mounting-components) - mounts a hyperstack component in an empty window
* [`before_mount`](/development-workflow/hyper-spec/03-methods-and-features#before_mount) - specifies a block of code to be executed before the first call to `mount`, `isomorphic` or `on_client`
* [`insert_html`](/development-workflow/hyper-spec/03-methods-and-features#insert_html) - insert some html into a page
* [`client_options`](/development-workflow/hyper-spec/03-methods-and-features#client-initialization-options) - allows options to be specified globally
* [`run_on_client`](/development-workflow/hyper-spec/03-methods-and-features#run_on_client) - same as `on_client` but no value is returned
* [`reload_page`](/development-workflow/hyper-spec/03-methods-and-features#reload_page) - resets the page environment
* [`add_class`](/development-workflow/hyper-spec/03-methods-and-features#add_class) - adds a CSS class
* [`size_window`](/development-workflow/hyper-spec/03-methods-and-features#size_window) - specifies how big the client window should be
* [`attributes_on_client`](/development-workflow/hyper-spec/03-methods-and-features#attributes_on_client) - returns any ActiveModel attributes loaded on the client

These methods are used after mounting a component to retrieve events sent outwards from the component:

* [`callback_history_for`](/development-workflow/hyper-spec/03-methods-and-features#retrieving-event-data-from-the-mounted-component)
* [`last_callback_for`](/development-workflow/hyper-spec/03-methods-and-features#retrieving-event-data-from-the-mounted-component)
* [`clear_callback_history_for`](/development-workflow/hyper-spec/03-methods-and-features#retrieving-event-data-from-the-mounted-component)
* [`event_history_for`](/development-workflow/hyper-spec/03-methods-and-features#retrieving-event-data-from-the-mounted-component)
* [`last_event_for`](/development-workflow/hyper-spec/03-methods-and-features#retrieving-event-data-from-the-mounted-component)
* [`clear_event_history_for`](/development-workflow/hyper-spec/03-methods-and-features#retrieving-event-data-from-the-mounted-component)

### Expectation Targets

These can be used within expectations replacing the `to` and `not_to` methods. The expectation expression must be inclosed in a block.

* [`on_client_to`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets), [`to_on_client_not`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets) - the expression will be evaluated on the client, and matched on the server.

These methods have the following aliases to make your specs more readable:

* [`to_on_client`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`on_client_to_not`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`on_client_not_to`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`to_not_on_client`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`not_to_on_client`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`to_then`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`then_to_not`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`then_not_to`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`to_not_then`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)
* [`not_to_then`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets)

in addition

* [`with`](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets) - can be chained with the above methods to pass data to initialize local variables on the client

### Other Debugging Aids

The following methods are used primarly at a debug break point, most require you use binding.pry as your debugger:

* [`to_js`](/development-workflow/hyper-spec/03-methods-and-features#to_js) - returns the ruby code compiled to JS.
* [`c?`](https://docs.hyperstack.org/development-workflow/hyper-spec/pages/-MVnGBmla0zujZfwV183#c?) - alias for `on_client`. &#x20;
* [`ppr`](/development-workflow/hyper-spec/03-methods-and-features#ppr) - print the results of the ruby expression on the client console.
* [`debugger`](/development-workflow/hyper-spec/03-methods-and-features#debugger) - Sets a debug breakpoint on code running on the client.
* [`open_in_chrome`](/development-workflow/hyper-spec/03-methods-and-features#open_in_chrome) - Opens a chrome browser that will load the current state. &#x20;
* [`pause`](/development-workflow/hyper-spec/03-methods-and-features#pause) - Halts execution on the server without blocking I/O.

### Available Webdrivers

HyperSpec comes integrated with Chrome and Chrome headless webdrivers. The default configuration will run using Chrome headless. To see what is going on set the `DRIVER` environment variable to `chrome`

```bash
DRIVER=chrome bundle exec rspec
```

### Timecop Integration

You can use the [`timecop` gem](https://github.com/travisjeffery/timecop) to control the flow of time within your specs. Hyperspec will coordinate things with the client so the time on the client is kept in sync with the time on the server. So for example if you use Timecop to advance time 1 day on the server, time on the browser will also advance by one day.

See the [Client Initialization Options](/development-workflow/hyper-spec/03-methods-and-features#client-initialization-options) section for how to control the client time zone, and clock resolution.

### The `no_reset` flag

By default the client environment will be reinitialized at the beginning of every spec. If this is not needed you can speed things up by adding the `no_reset` flag to a block of specs.

### Known Issues

See the last section below for known issues.

## Details

### The `on_client` method

The on\_client method takes a block. The ruby code inside the block will be executed on the client, and the result will be returned.

```ruby
  it 'will print a message on the client' do
    on_client do
      puts 'hey I am running here on the client!'
    end
  end
```

If the block returns a promise Hyperspec will wait for the promise to be resolved (or rejected) before returning. For example:

```ruby
  it 'waits for a promise' do
    start_time = Time.now
    result = on_client do
      promise = Promise.new
      after(10.seconds) { promise.resolve('done!') }
      promise
    end
    expect(result).to eq('done!')
    expect(Time.now-start_time).to be >= 10.seconds
  end
```

> HyperSpec will do its best to reconstruct the result back on the server in some sensible way. Occasionally it just doesn't work, in which case you can end the block with a `nil` or some other simple expression, or use the `run_on_client` method, which does not return the result.

### Accessing variables on the client

It is often useful to pass variables from the spec to the client. Hyperspec will copy all your local variables, memoized variables, and instance variables known at the time the `on_client` block is compiled to the client.\</br>

```ruby
  let!(memoized) { 'a memoized variable' }
  it 'will pass variables to the client' do
    local = 'a local variable'
    @instance = 'an instance variable'
    result = on_client { [memoized, local, @instance] }
    expect(result).to eq [memoized, local, @instance]
  end
```

> Note that memoized variables are not initialized until first accessed, so you probably want to use the let! method unless you are sure you are accessing the memoized value before sending it to the client.

The value of instance variables initialized on the client are preserved across blocks executed on the client. For example:

```ruby
  it 'remembers instance variables' do
    on_client { @total = 0 }
    10.times do |i|
      # note how we are passing i in
      on_client { @total += i }
    end
    result = on_client { @total }
    expect(result).to eq(10 * 11 / 2)
  end
```

> Be especially careful of this when using the [`no_reset` flag](/development-workflow/hyper-spec/03-methods-and-features#the-no_reset-flag) as instance variables will retain their values between each spec in this mode.

#### White and Black Listing Variables

By default all local variables, memoized variables, and instance variables in scope in the spec will be copied to the client. This can be controlled through the `include_vars` and `exclude_vars` [client options](/development-workflow/hyper-spec/03-methods-and-features#client-initialization-options).

`include_vars` can be set to

* an array of symbols: only those vars will be copied,
* a single symbol: only that var will be copied,
* any other truthy value: all vars will be copied (the default)
* or nil, false, or an empty array: no vars will be copied.

`exclude_vars` can be set to

* an array of symbols - those vars will **not** be copied,
* a single symbol - only that var will be excluded,
* any other truthy value - no vars will be copied,
* or nil, false, or an empty array - all vars will be copied (the default).

Examples:

```ruby
  # don't copy vars at all.
  client_option exclude_vars: true
  # only copy var1 and the instance var @var2
  client_option include_vars: [:var1, :@var2]
  # only exclude foo_var
  client_option exclude_vars: :foo_var
```

Note that the exclude\_vars list will take precedence over the include\_vars list.

The exclude/include lists can be overridden on an individual call to on\_client by providing a hash of names and values to on\_client:

```ruby
  result = on_client(var: 12) { var * var }
  expect(result).to eq(144)
```

You can do the same thing on expectations using the `with` method - See [Client Expectation Targets](/development-workflow/hyper-spec/03-methods-and-features#client-expectation-targets).

### The `isomorphic` method

The `isomorphic` method works the same as `on_client` but in addition it also executes the same block on the server. It is especially useful when doing some testing of ActiveRecord models, where you might want to modify the behavior of the model on server and the client.

```ruby
  it 'can run code the same everywhere!' do
    isomorphic do
      def factorial(x)
        x.zero? ? 1 : x * factorial(x - 1)
      end
    end

    on_the_client = on_client { factorial(7) }
    on_the_server = factorial(7)
    expect(on_the_client).to eq(on_the_server)
  end
```

### Client Initialization Options

The first time a spec runs code on the client, it has to initialize a browser context. You can use the `client_options` (aka `client_option`) method to specify the following options when the page is loaded.

* `time_zone` - browsers always run in the local time zone, if you want to force the browser to act as if its in a different zone, you can use the time\_zone option, and provide any valid zone that the rails `in_time_zone` method will accept.<br>

  Example: `client_option time_zone: 'Hawaii'`
* `clock_resolution`:  Indicates the resolution that the simulated clock will run at on the client, when using the TimeCop gem.  The default value is 20 (milliseconds).
* `include_vars`: white list of all vars to be copied to the client.  See [Accessing Variables on the Client](/development-workflow/hyper-spec/03-methods-and-features#accessing-variables-on-the-client) for details.
* `exclude_vars`: black list of all vars not to be copied to the client.  See [Accessing Variables on the Client](/development-workflow/hyper-spec/03-methods-and-features#accessing-variables-on-the-client) for details.
* `render_on`: `:client_only` (default), `:server_only`, or `:both` &#x20;

  Hyperstack components can be prerendered on the server.  The `render_on` option controls this feature.  For example `server_only` is useful to insure components are properly prerendered.  *See the `mount` method* [*below*](/development-workflow/hyper-spec/03-methods-and-features#mounting-components) *for more details on rendering components*
* `no_wait`: After the page is loaded the system will by default wait until all javascript requests to the server complete before proceeding. Specifying `no_wait: true` will skip this.
* `javascript`: The javascript asset to load when mounting the component.  By default it will be `application` (.js is assumed).  Note that the standard Hyperstack configuration will compile all the client side Ruby assets as well as javascript packages into the `application.js` file, so the default will work fine.
* `style_sheet`: The style sheet asset to load when mounting the component.  By default it will be `application` (.css is assumed).
* `controller` - **(expert zone!)** specify a controller that will be used to mount the

  component.  By default hyper-spec will build a controller and route to handle the request from the client to mount the component.

Any other options not listed above will be passed along to the Rail's controller `render` method. So for example you could specify some other specific layout using `client_option layout: 'special_layout'`

Note that this method can be used in the `before(:each)` block of a spec context to provide options for all the specs in the block.

### Mounting Components

The `mount` method is used to render a component on a page:

```ruby
  it 'can display a component for me' do
    mount 'SayHello', name: 'Lannar' do
      class SayHello < HyperComponent
        param :name
        render(DIV) do
          "Hello #{name}!"
        end
      end
    end

    expect(page).to have_content('Hello Lannar')
  end
```

The `mount` method has a few options. In it's simplest form you specify just the name of the component that is already defined in your hyperstack code and it will be mounted.

You can add parameters that will be passed to the component as in the above example. As the above example also shows you can also define code within the block. This is just shorthand for defining the code before hand using `on_client`. The code does not have to be the component being mounted, but might be just some logic to help with the test.

In addition `mount` can take any of the options provided to `client_options` (see above.) To provide these options, you must provide a (possibly) empty params hash. For example:

```ruby
mount 'MyComponent', {... params ... }, {... opts ... }
```

### Retrieving Event Data From the Mounted Component

Components *receive* parameters, and may send callbacks and events back out. To test if a component has sent the appropriate data you can use the following methods:

* `callback_history_for`
* `last_callback_for`
* `clear_callback_history_for`
* `event_history_for`
* `last_event_for`
* `clear_event_history_for`

```ruby
  it 'can check on a clients events and callbacks' do
    mount 'BigTalker' do
      class BigTalker < HyperComponent
        fires :i_was_clicked
        param :call_me_back, type: Proc

        before_mount { @click_counter = 0 }

        render(DIV) do
          BUTTON { 'click me' }.on(:click) do
            @click_counter += 1
            i_was_clicked!
            call_me_back.call(@click_counter)
          end
        end
      end
    end
    3.times do
      find('button').click
    end
    # the history is an array, one element for each item in the history
    expect(event_history_for(:i_was_clicked).length).to eq(3)
    # each item in the array is itself an array of the arguments
    expect(last_call_back_for(:call_me_back)).to eq([3])
    # clearing the history resets the array to empty
    clear_event_history_for(:i_was_clicked)
    expect(event_history_for(:i_was_clicked).length).to eq(0)
  end
```

> Note that you must declare the params as type `Proc`, or use the `fires` method to declare an event for the history mechanism to work.

### Other Helpers

#### `before_mount`

Specifies a block of code to be executed before the first call to `mount`, `isomorphic` or `on_client`. This is primarly useful to add to an rspec `before(:each)` block containing common client code needed by all the specs in the context.

> Unlike `mount`, `isomorphic` and `on_client`, `before_mount` does not load the client page, but will wait for the first of the other methods to be called.

#### `add_class`

Adds a CSS class. The first parameter is the name of the class, and the second is a hash of styles, represented in the React [style format.](https://reactjs.org/docs/dom-elements.html#style)

Example: `add_class :some_class, borderStyle: :solid` adds a class with style `border-style: 'solid'`

#### `run_on_client`

same as `on_client` but no value is returned. Useful when the return value may be too complex to marshall and unmarshall using JSON.

#### `reload_page`

Shorthand for `mount` with no parameters. Useful if you need to reset the client within a spec.

#### `size_window`

Indicates the size of the browser window. The values can be given either symbolically or as two numbers (width and height). Predefined sizes are:

* `:small`: 480 x 320
* `:mobile` 640 x 480
* `:tablet` 960 x 64,
* `:large` 1920 x 6000
* `:default` 1024 x 768

All of the above can be modified by providing the `:portrait` option as the first or second parameter.

So for example the following are all equivalent:

* `size_window(:small, :portrait)`
* `size_window(:portrait, :small)`
* `size_window(320, 480)`

#### `attributes_on_client`

returns any `ActiveModel` attributes loaded on the client. HyperModel will normally begin a load cycle as soon as you access the attribute on the client. However it is sometimes useful to see what attributes have already been loaded.

#### `insert_html`

takes a string and inserts it into test page when it is mounted. Useful for testing code that is not dependent on Hyper Components. For example an Opal library that adds some jQuery extensions.

### Client Expectation Targets

These can be used within expectations replacing the `to` and `not_to` methods. The expectation expression must be inclosed in a block.

For example:

```ruby
it 'has built-in expectation targets' do
  expect { RUBY_ENGINE }.on_client_to eq('opal')
end
```

The above expectation is short for saying:

```ruby
  result = on_client { RUBY_ENGINE }
  expect(result).to eq('opal')
```

These methods have the following aliases to make your specs more readable:

* `to_on_client`
* `on_client_to_not`
* `on_client_not_to`
* `to_not_on_client`
* `not_to_on_client`
* `to_then`
* `then_to_not`
* `then_not_to`
* `to_not_then`
* `not_to_then`

The `then` variants are useful to note that the spec involves a promise, but it does no explicit checking that the result comes from a promise.

In addition the `with` method can be chained with the above methods to pass data to initialize local variables on the client:

```ruby
  it 'can pass values to the client using the with method' do
    expect { foo * foo }.with(foo: 12).to_on_client eq(144)
  end
```

By default HyperSpec will copy all local variables, memoized variables, and instance variables defined in a spec to the client. The specific variables can also be white listed and black listed. The `with` method overrides any white or black listed values. So for example if you prefer to use the more explicit `with` method to pass values to the client, you can add `client_option exclude_vars: true` in a `before(:all)` block in your spec helper. See [Accessing Variables on the Client](/development-workflow/hyper-spec/03-methods-and-features#accessing-variables-on-the-client) for details.

### Useful Debug Methods

These methods are primarily designed to help debug code and specs.

#### `c?`

Shorthand for `on_client`, useful for entering expressions in the pry console, to investigate the state of the client.

```ruby
pry:> c? { puts 'hello on the console' } # prints hello on the client
-> nil
```

#### `to_js`

Takes a block like `on_client` but rather than running the code on the client, simply returns the resulting code. This is useful for debugging obscure problems when the Opal compiler or some feature of Hyperspec is suspected as the issue.

#### `ppr`

Takes a block like `on_client` and prints the result on the client console using JS console.log. Equivalent to doing

```ruby
  on_client do  
    begin
      ...
    end.tap { |r| `console.log(r)` }
  end
```

This is useful when the result cannot be usefully returned to the server, or when the result of interest is better looked at as the raw javascript object.

#### `debugger`

This psuedo method can be inserted into any code executed on the client. It will cause the code to stop, and enter a *javascript* read-eval loop, within the debug console.

Unfortunately ATM we do not have the technology to enter a *Ruby* read-eval loop at an arbitrary point on the client.

> Note: due to a bug in the Opal compiler your code should not have `debugger` as the last expression in a method or a block. In this situation add any expression (such as nil) after the debugger statement.
>
> ```ruby
> def foo
>   ... some code ...
>   debugger  # this will fail with a compiler syntax error
> end
> ```

#### `open_in_chrome`

By default specs are run with headless chrome, so there is no visible browser window. The `open_in_chrome` method will open a browser window, and load it with the current state.

You can also run specs in a visible chrome window by setting the `DRIVER` environment variable to `chrome`. i.e. (`DRIVER=chrome bundle exec rspec ...`)

#### `pause`

The method is typically not needed assuming you are using a multithreaded server like Puma. If for whatever reason the pry debug session is not multithreaded, *and* you want to try some kind of experiment on the javascript console, *and* those experiments make requests to the server, you may not get a response, because all threads are in use.

You can resolve this by using the `pause` method in the debug session which will put the server debug session into a non-blocking loop. You can then experiment in the JS console, and when done release the pause by executing `go()` in the *javascript* debug console.

### Known Issues

#### Using `visit` and the Application Layout

Currently this is not well integrated (see [issue 398](https://github.com/hyperstack-org/hyperstack/issues/398)). If you want to visit a page on the website using `visit`, the following will not work: Timecop integration, and the `insert_html` and `before_mount` methods. You will also have to execute this line in your spec:

```ruby
page.instance_variable_set("@hyper_spec_mounted", true)
```

Upvote issue 398 if this presents a big problem for you.

#### Some Complex Expressions Do Not Work

> This has been fixed in Parser version 2.7 which works with Opal 1.0\
> So the issue is only with older versions of Opal.

[Issue 127](https://github.com/hyperstack-org/hyperstack/issues/127)

You may get an error like this when running a spec:

```
(string):1:20: error: unexpected token tOP_ASGN
(string):1: hash.[]("foo") += 1
(string):1:
```

The problem is the unparser incorrectly generates `hash.[]("foo") += 1` instead of `hash['foo'] += 1`.

The good news its pretty easy to find such expressions and replace them with something like

`hash["foo"] = hash["foo"] + 1`


# Using with Rack

Hyperspec will run with Rails out of the box, but you can also use Hyperspec with any Rack application, with just a little more setup. For example here is a sample configuration setup with Sinatra:

```ruby
# Gemfile
...

gem "sinatra"
gem "rspec"
gem "pry"
gem "opal"
gem "opal-sprockets"
gem "rack"
gem "puma"
group :test do
  # gem 'hyper-spec', '~> 1.0.alpha1.0'
  # or to use edge:
  gem 'hyper-spec',
      git: 'git://github.com/hyperstack-org/hyperstack.git',
      branch: 'edge',
      glob: 'ruby/*/*.gemspec'
end
```

```ruby
# spec/spec_helper.rb

require "bundler"
Bundler.require
ENV["RACK_ENV"] ||= "test"

# require your application files as needed
require File.join(File.dirname(__FILE__), "..", "app.rb")

# bring in needed support files
require "rspec"
require "rack/test"
require "hyper-spec/rack"

# assumes your sinatra app is named app
Capybara.app = HyperSpecTestController.wrap(app: app)

set :environment, :test
set :run, false
set :raise_errors, true
set :logging, false
```

## Details

The interface between Hyperspec and your application environment is defined by the `HyperspecTestController` class. This file typically includes a set of helper methods from `HyperSpec::ControllerHelpers`, which can then be overridden to give whatever behavior your specific framework needs. Have a look at the `hyper-spec/rack.rb` and `hyper-spec/controller_helpers.rb` files in the Hyperspec gem directory.

## Example

A complete (but very simple) example is in this repos `ruby/examples/misc/sinatra_app` directory


# Deploy To Heroku

There are a number of issues and additional items that need to been done when deploying to Heroku (or other production environments.) Even if not deploying to Heroku these steps will cover most of the gotchas that you will encounter.

If you do find any problems please log an issue, or better yet do a pull request on this page.

1. **You need to use postgresql rather than sqlite or mysql.** You can find instructions on how to do this online, or better yet when you create your rails app, create it from the beginning with postgresql: <https://www.digitalocean.com/community/tutorials/how-to-set-up-ruby-on-rails-with-postgres>
2. **Remove `app/models/application_record.rb`** This is no longer needed due to a recent rails fix, and confuses Heroku.
3. **Use harmonly uglifier.** In config/environments/production.rb you need to change this line from:\
   `config.assets.js_compressor = :uglifier`\
   to\
   `config.assets.js_compressor = Uglifier.new(harmony: true)`
4. **Insure webpacker:compile occurs before assets:precompile:** at the end of the `Rakefile` (in the root directory) add this line:\
   `Rake::Task["assets:precompile"].enhance(['yarn:install', 'webpacker:compile'])`
5. **Setup your database** Make sure you run\
   `Heroku run rake db:migrate`
6. **Update your production policies** By default the Hyperstack installer will leave your Policies wide open but **not** in production.\
   For a production app you will want to add restrictive Policies to protect your data. If you just want to get things working on Heroku you can remove the guard from the end of the `policies/application.rb` file.
7. Add `stylesheet_pack_tag`s: Hyperstack does not automatically pull in the `.css` packs. Instead you have to add one or both these lines to your layouts, if you are requiring css assets in the pack files:\
   `<%= stylesheet_pack_tag 'client_only' %>`\
   If you are requiring css libraries in the `client_only.js` pack file\
   and\
   `<%= stylesheet_pack_tag 'client_and_server' %>`\
   If you are requiring css libraries in the `client_and_server.js` pack file
8. Setup ActionCable (see [full instructions](https://blog.Heroku.com/real_time_rails_implementing_websockets_in_rails_5_with_action_cable#deploying-our-application-to-Heroku) for details) provision Redis on Heroku `Heroku addons:add redistogo`\
   then get the Heroku url: `Heroku config --app action-cable-example | grep REDISTOGO_URL`\
   use the url in config/cable.yml (in the production section)\
   in config/environments/production.rb add these two lines:\
   `config.web_socket_server_url = "wss://your-app.Herokuapp.com/cable"`\
   `config.action_cable.allowed_request_origins = ['https://your-app.Herokuapp.com', 'http://action-your-app.Herokuapp.com']`

## On Going Development

After updating anything in the hyperstack initializer you will need to force Heroku to clear the cache:

First install the Heroku-repo plugin (on your console) `$ Heroku plugins:install Heroku-repo`

and then to clear the cache do:

`$ Heroku repo:purge_cache -a appname` `$ git commit --allow-empty -m "Purge cache"` `$ git push Heroku master`


# Tutorial


# TodoMVC Tutorial Part I

## Prerequisites

* Linux or Mac system

  (Android, ChromeOS and Windows are not supported)
* Ruby on Rails must be installed: <https://rubyonrails.org/>
* NodeJS must be installed: <https://nodejs.org>
* Yarn must be installed: <https://yarnpkg.com/en/docs/install>

## The goals of this tutorial

In this tutorial, you will build the classic [TodoMVC](http://todomvc.com) application using Hyperstack. This tutorial will demonstrate several key Hyperstack concepts - client side Components and Isomorphic Models.

The finished application will

1. have the ability to add and edit todos;
2. be able change the complete/incomplete state;
3. filter the list of displayed todos to show all, complete, or incomplete (active) todos;
4. have html5 history so that as the filter changes so does the URL;
5. have server side persistence;
6. and synchronization across multiple browser windows.

You will write less than 100 lines of code, and the tutorial should take about 1-2 hours to complete.

## Skills required

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

## Chapter 1: Setting Things Up

First you need to create a new project for this tutorial.

```
rails new todo-demo --skip-test
```

This command will create a new Rails project.

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

Now

```
cd todo-demo
```

which will change the working directory to your new todo rails project.

Now run

```
bundle add 'rails-hyperstack' --version "~> 1.0.alpha1.0"
```

which will install the `rails-hyperstack` 'gem' into the system.

Once the gem is installed run

```
bundle exec rails hyperstack:install
```

to complete the hyperstack installation.

Finally find the `config/initializers/hyperstack.rb` file, and make sure that this line is **not** commented out:

```ruby
Hyperstack.import 'hyperstack/component/jquery', client_only: true
```

> Ignore any comments saying that it should be commented out, this is a typo in the current installer

### Start the Rails app

In the console run the following command to start the Rails server and Hotloader.

```
bundle exec foreman start
```

For the rest of the tutorial you will want to keep foreman running in the background and have a second console window open in the `todo-demo` directory to execute various commands.

Navigate to <http://localhost:5000/> in your browser and you should see the word **Hello world from Hyperstack!** displayed on the page. Hyperstack will need a moment to start and pre-compile with the first request.

**Note:** *you will be using port 5000 not the more typical 3000, this is because of the way the Hotloader is configured.*

### Make a Simple Change

Bring up your favorite editor on the `todo-demo` directory. You will see folders like `app`, `bin`, `config` and `db`. These have all been preinitialized by Rails and Hyperstack gems.

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

```ruby
# app/hyperstack/component/app.rb

# This is your top level component, the rails router will
# direct all requests to mount this component.  You may
# then use the Route psuedo component to mount specific
# subcomponents depending on the URL.

class App < HyperComponent
  include Hyperstack::Router

  # define routes using the Route psuedo component.  Examples:
  # Route('/foo', mounts: Foo)                : match the path beginning with /foo and mount component Foo here
  # Route('/foo') { Foo(...) }                : display the contents of the block
  # Route('/', exact: true, mounts: Home)     : match the exact path / and mount the Home component
  # Route('/user/:id/name', mounts: UserName) : path segments beginning with a colon will be captured in the match param
  # see the hyper-router gem documentation for more details

  render do
    H1 { "Hello world from Hyperstack!" }
  end
end
```

Change the string displayed to something like: `"Todo App Coming Soon"`. You will see the display instantly change when you save the file.

You can also delete the comments as we will go over details of routing later.

> The Hyperstack UI is built from components. Each component is defined by a subclass of HyperComponent. In some cases there will only be one instance of the class displayed, and as we will see at other times the class is reused to display multiple components. If you are familiar with Rails or the MVC structure then you can think of Components as views that continuously update as the state of the application changes.

## Chapter 2:  Hyperstack Models are Rails Models

We are going to add our Todo Model, and discover that Hyperstack models are in fact Rails ActiveRecord models.

* You can access your rails models on the client using the same syntax you use on the server.
* Changes on the client are mirrored on the server.
* Changes to models on the server are synchronized with all participating browsers.
* Data access is protected by a robust *policy* mechanism.

> A Rails ActiveRecord Model is a Ruby class that is backed by a database table. In this example we will have one model class called `Todo`. When manipulating models, Rails automatically generates the necessary SQL code for you. So when `Todo.all` is evaluated Rails generates the appropriate SQL and turns the result of the query into appropriate Ruby data structures.

**Hyperstack Models are extensions of ActiveRecord Models that synchronize the data between the client and server automatically for you. So now `Todo.all` can be evaluated on the server or the client.**

Okay lets see it in action:

1. **Add the Todo Model:**

As stated earlier we keep *foreman* running in the first console and open a second console. In this second console window run **on a single line**:

```
bundle exec rails g model Todo title:string completed:boolean priority:integer
```

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.

Now look in the db/migrate/ directory, and edit the migration file you have just created. The file will be titled with a long string of numbers then "create\_todos" at the end. Change the line creating the completed boolean field so that it looks like this:

```ruby
...
t.boolean :completed, null: false, default: false
...
```

For details on 'why' see [this blog post.](https://robots.thoughtbot.com/avoid-the-threestate-boolean-problem) Basically this insures `completed` is treated as a real boolean, and will avoid having to check between `false` and `null` later on.

Now run:

```
bundle exec rails db:migrate
```

which will create the table.

1. **Make Your Model Public:**

Move `models/todo.rb` to `hyperstack/models`

This will make the model accessible on the clients *and the server*, subject to any data access policies.

**Note:** *The hyperstack installer adds a policy that gives full permission to all clients but only in development and test modes. Have a look at `app/policies/application_policy` if you are interested.*

1. **Try It:**

Now change your `App` component's render method to:

```ruby
class App < HyperComponent
  include Hyperstack::Router
  render do
    H1 { "Number of Todos: #{Todo.count}" }
  end
end
```

You will now see **Number of Todos: 0** displayed.

Now start a rails console

```
bundle exec rails c
```

and type:

```ruby
Todo.create(title: 'my first todo')
```

This will create a new Todo in the server's database, which will cause your Hyperstack application to be updated and you will see the count change to 1!

Try it again:

```ruby
Todo.create(title: 'my second todo')
```

and you will see the count change to 2!

Are we having fun yet? I hope so! As you can see Hyperstack is synchronizing the Todo model between the client and server. As the state of the database changes, Hyperstack buzzes around updating whatever parts of the DOM were dependent on that data (in this case the count of Todos).

Notice that we did not create any APIs to achieve this. Data on the server is synchronized with data on the client for you.

## Chapter 3: Creating the Top Level App Structure

Now that we have all of our pieces in place, lets build our application.

Replace the entire contents of `app.rb` with:

```ruby
# app/hyperstack/components/app.rb
class App < HyperComponent
  include Hyperstack::Router
  render(SECTION) do
    Header()
    Index()
    Footer()
  end
end
```

After saving you will see the following error displayed:

**Uncaught error: Header: undefined method \`Header' for # in App (created by Hyperstack::Internal::Component::TopLevelRailsComponent) in Hyperstack::Internal::Component::TopLevelRailsComponent**

because we have not defined the three subcomponents. Lets define them now:

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

```ruby
# app/hyperstack/components/header.rb
class Header < HyperComponent
  render(HEADER) do
    'Header will go here'
  end
end
```

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  render(SECTION) do
    'List of Todos will go here'
  end
end
```

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  render(DIV) do
    'Footer will go here'
  end
end
```

Once you add the Footer component you should see:

Header will go here List of Todos will go here Footer will go here \</div>

If you don't, restart the server (*foreman* in the first console), and reload the browser.

Notice how the usual HTML tags such as DIV, SECTION, and HEADER are all available as well as all the other HTML and SVG tags.

> Hyperstack uses the following conventions to easily distinguish between HTML tags, application defined components and other helper methods:
>
> * HTML tags are in all caps
> * Application components are CamelCased
> * other helper methods are snake\_cased

## Chapter 4: Listing the Todos, Hyperstack Params, and Prerendering

To display each Todo we will create a TodoItem component that takes a parameter:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    todo.title
  end
end
```

We can use this component in our Index component:

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  render(SECTION) do
    UL do
      Todo.each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end
```

Now you will see something like

Header will go here Footer will go here \</div>

As you can see components can take parameters (or props in react.js terminology.)

> *Rails uses the terminology params (short for parameters) which have a similar purpose to React props, so to make the transition more natural for Rails programmers Hyperstack uses params, rather than props.*

Params are declared using the `param` macro which creates an *accessor* method of the same name within the component.

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

Now go back to Rails console and type

```ruby
Todo.last.update(title: 'updated todo')
```

and you will see the last Todo in the list changing.

Try adding another Todo using `create` like you did before. You will see the new Todo is added to the list.

## Chapter 5: Adding Inputs to Components

So far we have seen how our components are synchronized to the data that they display. Next let's add the ability for the component to *change* the underlying data.

First add an `INPUT` html tag to your TodoItem component like this:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    INPUT(type: :checkbox, checked: todo.completed)
    todo.title
  end
end
```

You will notice that while it does display the checkboxes, you can not change them by clicking on them.

For now we can change them via the console like we did before. Try executing

```ruby
Todo.last.update(completed: true)
```

and you should see the last Todo's `completed` checkbox changing state.

To make our checkbox input change its own state, we will add an `event handler` for the change event:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    INPUT(type: :checkbox, checked: todo.completed)
    .on(:change) { todo.update(completed: !todo.completed) }
    todo.title
  end
end
```

It reads like a good novel doesn't it? On the `change` event update the todo, setting the completed attribute to the opposite of its current value. The rest of coordination between the database and the display is taken care of for you by the Hyperstack.

After saving your changes you should be able change the `completed` state of each Todo, and check on the rails console (say by checking `Todo.last.completed`) and you will see that the value has been persisted to the database. You can also demonstrate this by refreshing the page.

We will finish up by adding a *delete* link at the end of the Todo item:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    INPUT(type: :checkbox, checked: todo.completed)
    .on(:change) { todo.update(completed: !todo.completed) }
    SPAN { todo.title } # See note below...
    A { ' -X-' }.on(:click) { todo.destroy }
  end
end
```

**Note:** *If a component or tag block returns a string it is automatically wrapped in a SPAN, to insert a string in the middle you have to wrap it a SPAN like we did above.*

I hope you are starting to see a pattern here. Hyperstack components determine what to display based on the `state` of some objects. External events, such as mouse clicks, the arrival of new data from the server, and even timers update the `state`. Hyperstack recomputes whatever portion of the display depends on the `state` so that the display is always in sync with the `state`. In our case the objects are the Todo model and its associated records, which have a number of associated internal `states`.

By the way, you don't have to use Models to have states. We will see later that states can be as simple as boolean instance variables.

## Chapter 6: Routing

Now that Todos can be *completed* or *active*, we would like our user to be able display either "all" Todos, only "completed" Todos, or "active" (or incomplete) Todos. We want our URL to reflect which filter is currently being displayed. So `/all` will display all todos, `/completed` will display the completed Todos, and of course `/active` will display only active (or incomplete) Todos. We would also like the root url `/` to be treated as `/all`

To achieve this we first need to be able to *scope* (or filter) the Todo Model. So let's edit the Todo model file so it looks like this:

```ruby
# app/hyperstack/models/todo.rb
class Todo < ApplicationRecord
  scope :completed, -> { where(completed: true)  }
  scope :active,    -> { where(completed: false) }
end
```

Now we can say `Todo.all`, `Todo.completed`, and `Todo.active`, and get the desired subset of Todos. You might want to try it now in the rails console.\
**Note:** *you will have to do a `reload!` to load the changes to the Model.*

We would like the URL of our App to reflect which of these *filters* is being displayed. So if we load

* `/all` we want the Todo.all scope to be run;
* `/completed` we want the Todo.completed scope to be run;
* `/active` we want the Todo.active scope to be run;
* `/` (by itself) then we should redirect to `/all`.

Having the application display different data (or whole different components) based on the URL is called routing.

Lets change `App` to look like this:

```ruby
# app/hyperstack/components/app.rb
class App < HyperComponent
  include Hyperstack::Router
  render(SECTION) do
    Header()
    Route('/', exact: true) { Redirect('/all') }
    Route('/:scope', mounts: Index)
    Footer()
  end
end
```

and the `Index` component to look like this:

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  include Hyperstack::Router::Helpers
  render(SECTION) do
    UL do
      Todo.send(match.params[:scope]).each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end
```

Lets walk through the changes:

* We mount the `Header` components as before.
* We then check to see if the current route exactly matches `/` and if it does, redirect to `/all`.
* Then instead of directly mounting the `Index` component, we *route* to it based on the URL.  In this case if the url must look like `/xxx`.
* `Index` now includes (mixes-in) the `Hyperstack::Router::Helpers` module which has methods like `match`.
* Instead of simply enumerating all the Todos, we decide which *scope* to filter using the URL fragment *matched* by `:scope`. &#x20;

Notice the relationship between `Route('/:scope', mounts: Index)` and `match.params[:scope]`:

During routing each `Route` is checked. If it *matches* then the indicated component is mounted, and the match parameters are saved for that component to use.

You should now be able to change the url from `/all`, to `/completed`, to `/active`, and see a different set of Todos. For example if you are displaying the `/active` Todos, you will only see the Todos that are not complete. If you check one of these it will disappear from the list.

> Rails also has the concept of routing, so how do the Rails and Hyperstack routers interact? Have a look at the config/routes.rb file. You will see a line like this: `get '/(*other)', to: 'hyperstack#app'` This is telling Rails to accept all requests and to process them using the `Hyperstack` controller, which will attempt to mount a component named `App` in response to the request. The mounted App component is then responsible for further processing the URL.
>
> For more complex scenarios Hyperstack provides Rails helper methods that can be used to mount components from your controllers, layouts, and views.

## Chapter 7:  Helper Methods, Inline Styling, Active Support and Router Nav Links

Of course we will want to add navigation to move between these routes. We will put the navigation in the footer:

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  def link_item(path)
    A(href: "/#{path}", style: { marginRight: 10 }) { path.camelize }
  end
  render(DIV) do
    link_item(:all)
    link_item(:active)
    link_item(:completed)
  end
end
```

Save the file, and you will now have 3 links, that you will change the path between the three options.

Here is how the changes work:

* Hyperstack is just Ruby, so you are free to use all of Ruby's rich feature set to structure your code.

  For example the `link_item` method is just a *helper* method to save us some typing.
* The `link_item` method uses the `path` argument to construct an HTML *Anchor* tag.
* Hyperstack comes with a large portion of the Rails active-support library.

  For the text of the anchor tag we use the active-support method `camelize`.
* Later we will add proper css classes, but for now we use an inline style.

  Notice that the css `margin-right` is written `marginRight`, and that `10px` can be expressed as the integer 10.

Notice that as you click each link the page reloads. **However** what we really want is for the links to simply change the route, without reloading the page.

To make this happen we will *mixin* some router helpers by *including* `HyperRouter::ComponentMethods` inside of class.

Then we can replace the anchor tag with the Router's `NavLink` component:

Change

```ruby
A(href: "/#{path}", style: { marginRight: 10 }) { path.camelize }
```

to

```ruby
NavLink("/#{path}", style: { marginRight: 10 }) { path.camelize }
# note that there is no href key in NavLink
```

Our component should now look like this:

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  include Hyperstack::Router::Helpers
  def link_item(path)
    NavLink("/#{path}", style: { marginRight: 10 }) { path.camelize }
  end
  render(DIV) do
    link_item(:all)
    link_item(:active)
    link_item(:completed)
  end
end
```

After this change you will notice that changing routes *does not* reload the page, and after clicking to different routes, you can use the browsers forward and back buttons.

How does it work? The `NavLink` component reacts to a click just like an anchor tag, but instead of changing the window's URL directly, it updates the *HTML5 history object.* Associated with this history is (hope you guessed it) *state*. So when the history changes it causes any components depending on the state of the URL to be re-rendered.

## Chapter 8: Create a Basic EditItem Component

So far we can mark Todos as completed, delete them, and filter them. Now we create an `EditItem` component so we can change the Todo title.

Add a new component like this:

```ruby
# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  render do
    INPUT(defaultValue: todo.title)
    .on(:enter) do |evt|
      todo.update(title: evt.target.value)
    end
  end
end
```

Before we use this component let's understand how it works.

* It receives a `todo` param which will be edited by the user;
* The `title` of the todo is displayed as the initial value of the input;
* When the user types the enter key the `todo` is updated.

Now update the `TodoItem` component replacing

```ruby
SPAN { todo.title }
```

with

```ruby
EditItem(todo: todo)
```

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.

## Chapter 9: Adding State to a Component, Defining Custom Events, and a Lifecycle Callback.

This all works, but it's hard to use. There is no feedback indicating that a Todo has been saved, and there is no way to cancel after starting to edit. We can make the user interface much nicer by adding *state* (there is that word again) to the `TodoItem`. We will call our state `editing`. If `editing` is true, then we will display the title in a `EditItem` component, otherwise we will display it in a `LABEL` tag. The user will change the state to `editing` by double clicking on the label. When the user saves the Todo, we will change the state of `editing` back to false. Finally we will let the user *cancel* the edit by moving the focus away (the `blur` event) from the `EditItem`. To summarize:

* User double clicks on any Todo title: editing changes to `true`.
* User saves the Todo being edited: editing changes to `false`.
* User changes focus away (`blur`) from the Todo being edited: editing changes to `false`.

In order to accomplish this our `EditItem` component is going to communicate to its parent via two application defined events - `saved` and `cancel`.

Add the following 5 lines to the `EditItem` component like this:

```ruby
# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  fires :saved                               # add
  fires :cancel                              # add
  after_mount { jQ[dom_node].focus }         # add

  render do
    INPUT(defaultValue: todo.title)
    .on(:enter) do |evt|
      todo.update(title: evt.target.value)
      saved!                                 # add
    end
    .on(:blur) { cancel! }                   # add
  end
end
```

The first two new lines add our custom events which will be *fired* by the component.

The next new line uses one of several *Lifecycle Callbacks*. In this case we need to move the focus to the `EditItem` component after it is mounted. The `jQ` method is Hyperstack's jQuery wrapper, and `dom_node` is the method that returns the actual dom node where this *instance* of the component is mounted. This is the `INPUT` html element as defined in the render method.

The `saved!` line will fire the saved event in the parent component. Notice that the method to fire a custom event is the name of the event followed by a bang (!).

Finally we add the `blur` event handler and fire our `cancel` event.

Now we can update our `TodoItem` component to react to three events: `double_click`, `saved` and `cancel`.

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    if @editing
      EditItem(todo: todo)
      .on(:saved, :cancel) { mutate @editing = false }
    else
      INPUT(type: :checkbox, checked: todo.completed)
      .on(:change) { todo.update(completed: !todo.completed) }
      LABEL { todo.title }
      .on(:double_click) { mutate @editing = true }
      A { ' -X-' }
      .on(:click) { todo.destroy }
    end
  end
end
```

All states in Hyperstack are simply Ruby instance variables (ivars for short which are variables with a leading @). Here we use the `@editing` ivar.

We have already used a lot of states that are built into the HyperModel and HyperRouter. The states of these components are built out of collections of instance variables like `@editing`.

In the `TodoItem` component the value of `@editing` controls whether to render the `EditItem` or the INPUT, LABEL, and Anchor tags.

Because `@editing` (like all ivars) starts off as nil, when the `TodoItem` first mounts, it renders the INPUT, LABEL, and Anchor tags. Attached to the label tag is a `double_click` handler which does one thing: *mutates* the component's state setting `@editing` to true. This then causes the component to re-render, and now instead of the three tags, we will render the `EditItem` component.

Attached to the `EditItem` component is the `saved` and `cancel` handler (which is shared between the two events) that *mutates* the component's state, setting `@editing` back to false.

Using and changing state in a component is as simple as reading or changing the value of some instance variables. The only caveat is that whenever you want to change a state variable whether it's a simple assignment or changing the internal value of a complex structure like a hash or array you use the `mutate` method to signal Hyperstack that that state is changing.

## Chapter 10: Using EditItem to create new Todos

Our `EditItem` component has a good robust interface. It takes a Todo, and lets the user edit the title, and then either save or cancel, using two custom events to communicate back outwards.

Because of this we can easily reuse `EditItem` to create new Todos. Not only does this save us time, but it also insures that the user interface acts consistently.

Update the `Header` component to use `EditItem` like this:

```ruby
# app/hyperstack/components/header.
class Header < HyperComponent
  before_mount { @new_todo = Todo.new }
  render(HEADER) do
    EditItem(todo: @new_todo)
    .on(:saved) { mutate @new_todo = Todo.new }
  end
end
```

What we have done is initialize an instance variable `@new_todo` to a new unsaved `Todo` item in the `before_mount` lifecycle method.

Then we pass the value `@new_todo` to EditItem, and when it is saved, we generate another new Todo and save it in the `new_todo` state variable.

When `Header`'s state is mutated, it will cause a re-render of the Header, which will then pass the new value of `@new_todo`, to `EditItem`, causing that component to also re-render.

We don't care if the user cancels the edit, so we simply don't provide a `:cancel` event handler.

Once the code is added a new input box will appear at the top of the window, and when you type enter a new Todo will be added to the list.

However you will notice that the value of new Todo input box does not clear. This is subtle problem but it's easy to fix.

React treats the `INPUT` tag's `defaultValue` specially. It is only read when the `INPUT` is first mounted, so it *does not react* to changes like normal parameters. Our `Header` component does pass in new Todo records, but even though they are changing React *does not* update the INPUT.

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, in this case it can also be used to indicate that the component needs to be remounted when the value of `key` is changed.

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, this will insure that as `todo` changes, we will re-initialize the `INPUT` tag.

```ruby
...
INPUT(defaultValue: todo.title, key: todo) # add the special key param
...
```

## Chapter 11: Adding Styling

We are just going to steal the style sheet from the benchmark Todo app, and add it to our assets.

**Go grab the file in this repo here:** <https://github.com/hyperstack-org/hyperstack/blob/edge/docs/tutorial/assets/todo.css> and copy it to a new file called `todo.css` in the `app/assets/stylesheets/` directory.

You will have to refresh the page after changing the style sheet.

Now its a matter of updating the css classes which are passed to components via the `class` parameter.

Let's start with the `App` component. With styling it will look like this:

```ruby
# app/hyperstack/components/app.rb
class App < HyperComponent
  include Hyperstack::Router
  render(SECTION, class: 'todo-app') do # add class todo-app
    Header()
    Route('/', exact: true) { Redirect('/all') }
    Route('/:scope', mounts: Index)
    Footer()
  end
end
```

The `Footer` component needs to have a `UL` added to hold the links nicely, and we can also use the `NavLinks` `active_class` param to highlight the link that is currently active:

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  include Hyperstack::Router::Helpers
  def link_item(path)
    # wrap the NavLink in a LI and
    # tell the NavLink to change the class to :selected when
    # the current (active) path equals the NavLink's path.
    LI { NavLink("/#{path}", active_class: :selected) { path.camelize } }
  end
  render(DIV, class: :footer) do   # add class footer
    UL(class: :filters) do         # wrap links in a UL element with class filters
      link_item(:all)
      link_item(:active)
      link_item(:completed)
    end
  end
end
```

For the Index component just add the `main` and `todo-list` classes.

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  include Hyperstack::Router::Helpers
  render(SECTION, class: :main) do         # add class main
    UL(class: 'todo-list') do              # add class todo-list
      Todo.send(match.params[:scope]).each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end
```

For the EditItem component we want the parent to pass any html parameters such as `class` along to the INPUT tag. We do this by adding the special `other` param that will collect any extra params, we then pass it along in to the INPUT tag. Hyperstack will take care of merging all the params together sensibly.

```ruby
# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  fires :saved
  fires :cancel
  other :etc  # can be named anything you want
  after_mount { jQ[dom_node].focus }
  render do
    INPUT(etc, defaultValue: todo.title, key: todo)
    .on(:enter) do |evt|
      todo.update(title: evt.target.value)
      saved!
    end
    .on(:blur) { cancel! }
  end
end
```

Now we can add classes to the TodoItem's list-item, input, anchor tags, and to the `EditItem` component:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI, class: 'todo-item') do # add the todo-item class
    if @editing
      EditItem(class: :edit, todo: todo)  # add the edit class
      .on(:saved, :cancel) { mutate @editing = false }
    else
      INPUT(type: :checkbox, class: :toggle, checked: todo.completed) # add the toggle class
      .on(:change) { todo.update(completed: !todo.completed) }
      LABEL { todo.title }
      .on(:double_click) { mutate @editing = true }
      A(class: :destroy) # add the destroy class and remove the -X- placeholder
      .on(:click) { todo.destroy }
    end
  end
end
```

In the Header we can send a different class to the `EditItem` component. While we are at it we will add the `H1 { 'todos' }` hero unit.

```ruby
# app/hyperstack/components/header.
class Header < HyperComponent
  before_mount { @new_todo = Todo.new }
  render(HEADER, class: :header) do                   # add the 'header' class
    H1 { 'todos' }                                    # add the hero unit.
    EditItem(class: 'new-todo', todo: @new_todo)      # add 'new-todo' class
    .on(:saved) { mutate @new_todo = Todo.new }
  end
end
```

At this point your Todo App should be properly styled.

## Chapter 12: Other Features

* **Show How Many Items Left In Footer**

  This is just a span that we add before the link tags list in the `Footer` component:

```ruby
...
render(DIV, class: :footer) do
  SPAN(class: 'todo-count') do
    # pluralize returns the second param (item) properly
    # pluralized depending on the first param's value.
    "#{pluralize(Todo.active.count, 'item')} left"
  end
  UL(class: :filters) do
...
```

* **Add 'placeholder' Text To Edit Item**

  `EditItem` should display a meaningful placeholder hint if the title is blank:

```ruby
...
INPUT(etc, placeholder: 'What is left to do today?',
            defaultValue: todo.title, key: todo)
.on(:enter) do |evt|
...
```

* **Don't Show the Footer If There are No Todos**

  In the `App` component add a *guard* so that we won't show the Footer if there are no Todos:

```ruby
...
Footer() unless Todo.count.zero?
...
```

Congratulations! you have completed the tutorial.

## Summary

You have built a small but feature rich full stack Todo application in less than 100 lines of code:

```
SLOC  
--------------
App:         9
Header:      8
Index:      10
TodoItem:   16
EditItem:   16
Footer:     16
Todo Model:  4
Rails Route: 4
--------------
Total:      83
```

The complete application is shown here:

```ruby
# app/hyperstack/components/app.rb
class App < HyperComponent
  include Hyperstack::Router
  render(SECTION, class: 'todo-app') do
    Header()
    Route('/', exact: true) { Redirect('/all') }
    Route('/:scope', mounts: Index)
    Footer() unless Todo.count.zero?
  end
end

# app/hyperstack/components/header.
class Header < HyperComponent
  before_mount { @new_todo = Todo.new }
  render(HEADER, class: :header) do
    H1 { 'todos' }
    EditItem(class: 'new-todo', todo: @new_todo)
    .on(:saved) { mutate @new_todo = Todo.new }
  end
end

# app/hyperstack/components/index.rb
class Index < HyperComponent
  include Hyperstack::Router::Helpers
  render(SECTION, class: :main) do
    UL(class: 'todo-list') do
      Todo.send(match.params[:scope]).each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end

# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  include Hyperstack::Router::Helpers
  def link_item(path)
    LI { NavLink("/#{path}", active_class: :selected) { path.camelize } }
  end
  render(DIV, class: :footer) do
    SPAN(class: 'todo-count') { "#{pluralize(Todo.active.count, 'item')} left" }
    UL(class: :filters) do
      link_item(:all)
      link_item(:active)
      link_item(:completed)
    end
  end
end

# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI, class: 'todo-item') do
    if @editing
      EditItem(class: :edit, todo: todo)
      .on(:saved, :cancel) { mutate @editing = false }
    else
      INPUT(type: :checkbox, class: :toggle, checked: todo.completed)
      .on(:change) { todo.update(completed: !todo.completed) }
      LABEL { todo.title }
      .on(:double_click) { mutate @editing = true }
      A(class: :destroy)
      .on(:click) { todo.destroy }
    end
  end
end

# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  fires :save
  fires :cancel
  other :etc
  after_mount { jQ[dom_node].focus }
  render do
    INPUT(etc, placeholder: 'What is left to do today?',
                defaultValue: todo.title, key: todo)
    .on(:enter) do |evt|
      todo.update(title: evt.target.value)
      saved!
    end
    .on(:blur) { cancel! }
  end
end

# app/hyperstack/models/todo.rb
class Todo < ApplicationRecord
  scope :completed, -> { where(completed: true)  }
  scope :active,    -> { where(completed: false) }
end

# config/routes.rb
Rails.application.routes.draw do
  mount Hyperstack::Engine => '/hyperstack'
  get '/(*other)', to: 'hyperstack#app'
end
```

## General troubleshooting

1: Wait. On initial boot it can take several minutes to pre-compile all the system assets.

2: Make sure to save (or better yet do a git commit) after every instruction so that you can backtrack.

3: Its possible to get things so messed up the hot-reloader will not work. Restart the server and reload the browser.

4: Reach out to us on Slack, we are always happy to help get you onboarded!


# TodoMVC Tutorial Part II

## Prerequisites

{ [Familarity with the TodoMVC tutorial Part I](https://docs.hyperstack.org/tutorial/todo) }

## The Goals of this Tutorial

In this tutorial, will investigate the advanced concepts of

1. *prerendering*,
2. the `while_loading` method and
3. optimizing ActiveRecord scopes to run on the client.

None of the techniques are necessary to build large complex applications, but they are useful to know to build the possible user experience.

## Skills required

Basic knowledge of Rails is helpful, and ability to follow the basic TodoMVC example on which this is based.

## Chapter 1: Setting Things Up

You can just read this tutorial, or if you want to follow along clone the working Todo application from this directory ... (or do we want to use the rail's template mechanism)

Once setup you should be able to start the rails app and hot reloader by running:

* `bundle exec foreman start`
* visit `localhost:5000`

Add about 4-6 random Todo's and mark about half as completed.

## Chapter 2:  Prerendering

When you first load the Todo app you will see a brief flash between the first load, and complete display of the list of Todos.

What is going on?

When you first load a Hyperstack application, you get all the code compiled in to Javascript, along with instructions to React on how to mount your top level component.

In our case the Todo App is mounted, which will then render the list of the Todo's. The list of Todo's are still on the server, so once the App is mounted and rendered we then have to wait a few 100 milliseconds for the actual data to arrive from the server.

These steps - starting Hyperstack, rendering the application, waiting for data, and re-rendering takes enough time and is visually noticeable as a brief flicker. On larger apps the download time of the Hyperstack will also be noticable.

The solution is called pre-rerendering. Prerendering runs all the steps before the page is delivered on the server. The result is that the page comes down already rendered in its final state. After page is loaded all the event handlers are then attached so that the page's components can continue to be updated reactively.

To turn on prerendering you change the Hyperstack configuration in the initializer from `prerendering = :off` to `:on`

```ruby
# config/initializers/hyperstack.rb
Hyperstack.configuration do |config|
  config.transport = :action_cable
  config.prerendering = :off # switch to on to turn on prerendering
  ...
end
```

Restart the server and prerendering is enabled.

Hypestack comes configured with prerendering off, because javsacript errors during prerendering occur on the server within the headless javscript environment and are thus much harder to debug. Once the application is working properly its easy to turn prerendering on.

> A Rails ActiveRecord Model is a Ruby class that is backed by a database table. In this example we will have one model class called `Todo`. When manipulating models, Rails automatically generates the necessary SQL code for you. So when `Todo.all` is evaluated Rails generates the appropriate SQL and turns the result of the query into appropriate Ruby data structures.

**Hyperstack Models are extensions of ActiveRecord Models that synchronize the data between the client and server automatically for you. So now `Todo.all` can be evaluated on the server or the client.**

Okay lets see it in action:

1. **Add the Todo Model:**

   In your second terminal window run **on a single line**:

   ```
    bundle exec rails g model Todo title:string completed:boolean priority:integer
   ```

   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.

   **VERY IMPORTANT!** Now look in the db/migrate/ directory, and edit the migration file you have just created. The file will be titled with a long string of numbers then "create\_todos" at the end. Change the line creating the completed boolean field so that it looks like this:

   ```ruby
    ...
    t.boolean :completed, null: false, default: false
    ...
   ```

   For details on 'why' see [this blog post.](https://robots.thoughtbot.com/avoid-the-threestate-boolean-problem) Basically this insures `completed` is treated as a true boolean, and will avoid having to check between `false` and `null` later on.

   Now run

   ```ruby
    bundle exec rails db:migrate
   ```

   which will create the table.
2. **Make Your Model Public:**

   *Move* `models/todo.rb` to `hyperstack/models`

   This will make the model accessible on the clients *and the server*, subject to any data access policies.

   *Note: The hyperstack installer adds a policy that gives full permission to all clients but only in development and test modes. Have a look at `app/policies/application_policy` if you are interested.*
3. **Try It**

   Now change your `App` component's render method to:

   ```ruby
   class App < HyperComponent
    include Hyperstack::Router
    render do
       H1 { "Number of Todos: #{Todo.count}" }
    end
   end
   ```

   You will now see **Number of Todos: 0** displayed.

   Now start a rails console

   ```ruby
    bundle exec rails c
   ```

   and type:

   ```ruby
     Todo.create(title: 'my first todo')
   ```

   This will create a new Todo in the server's database, which will cause your Hyperstack application to be updated and you will see the count change to 1!

   Try it again:

   ```ruby
     Todo.create(title: 'my second todo')
   ```

   and you will see the count change to 2!

Are we having fun yet? I hope so! As you can see Hyperstack is synchronizing the Todo model between the client and server. As the state of the database changes, Hyperstack buzzes around updating whatever parts of the DOM were dependent on that data (in this case the count of Todos).

Notice that we did not create any APIs to achieve this. Data on the server is synchronized with data on the client for you.

## Chapter 3: Creating the Top Level App Structure

Now that we have all of our pieces in place, lets build our application.

Replace the entire contents of `app.rb` with:

```ruby
# app/hyperstack/components/app.rb
class App < HyperComponent
  include Hyperstack::Router
  render(SECTION) do
    Header()
    Index()
    Footer()
  end
end
```

After saving you will see the following error displayed:

**Uncaught error: Header: undefined method \`Header' for #**\
**in App (created by Hyperstack::Internal::Component::TopLevelRailsComponent)**\
**in Hyperstack::Internal::Component::TopLevelRailsComponent**

because have not defined the three subcomponents. Lets define them now:

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

```ruby
# app/hyperstack/components/header.rb
class Header < HyperComponent
  render(HEADER) do
    'Header will go here'
  end
end
```

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  render(SECTION) do
    'List of Todos will go here'
  end
end
```

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  render(DIV) do
    'Footer will go here'
  end
end
```

Once you add the Footer component you should see:

Header will go here List of Todos will go here Footer will go here \</div>\
If you don't, restart the server, and reload the browser.

Notice how the usual HTML tags such as DIV, SECTION, and HEADER are all available as well as all the other HTML and SVG tags.

> Hyperstack uses the following conventions to easily distinguish between HTML tags, application defined components and other helper methods:
>
> * HTML tags are in all caps
> * Application components are CamelCased
> * other helper methods are snake\_cased

## Chapter 4: Listing the Todos, Hyperstack Params, and Prerendering

To display each Todo we will create a TodoItem component that takes a parameter:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    @Todo.title
  end
end
```

We can use this component in our Index component:

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  render(SECTION) do
    UL do
      Todo.each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end
```

Now you will see something like

Header will go here\
Footer will go here \</div>

As you can see components can take parameters (or props in react.js terminology.)

> *Rails uses the terminology params (short for parameters) which have a similar purpose to React props, so to make the transition more natural for Rails programmers Hyperstack uses params, rather than props.*

Params are declared using the `param` macro and are accessed via Ruby *instance variables*. Notice that the instance variable name is *CamelCased* so that it is easily distinguished from other instance variables.

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

Now go back to Rails console and type

```ruby
  Todo.last.update(title: 'updated todo')
```

and you will see the last Todo in the list changing.

Try adding another Todo using `create` like you did before. You will see the new Todo is added to the list.

## Chapter 5: Adding Inputs to Components

So far we have seen how our components are synchronized to the data that they display. Next let's add the ability for the component to *change* the underlying data.

First add an `INPUT` html tag to your TodoItem component like this:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    INPUT(type: :checkbox, checked: @Todo.completed)
    @Todo.title
  end
end
```

You will notice that while it does display the checkboxes, you can not change them by clicking on them.

For now we can change them via the console like we did before. Try executing

```ruby
  Todo.last.update(completed: true)
```

and you should see the last Todo's `completed` checkbox changing state.

To make our checkbox input change its own state, we will add an `event handler` for the change event:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    INPUT(type: :checkbox, checked: @Todo.completed)
    .on(:change) { @Todo.update(completed: !@Todo.completed) }
    @Todo.title
  end
end
```

It reads like a good novel doesn't it? On the `change` event update the todo, setting the completed attribute to the opposite of its current value. The rest of coordination between the database and the display is taken care of for you by the Hyperstack.

After saving your changes you should be able change the `completed` state of each Todo, and check on the rails console (say by checking `Todo.last.completed`) and you will see that the value has been persisted to the database. You can also demonstrate this by refreshing the page.

We will finish up by adding a *delete* link at the end of the Todo item:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    INPUT(type: :checkbox, checked: @Todo.completed)
    .on(:change) { @Todo.update(completed: !@Todo.completed) }
    SPAN { @Todo.title } # See note below...
    A { ' -X-' }.on(:click) { @Todo.destroy }
  end
end
```

*Note: If a component or tag block returns a string it is automatically wrapped in a SPAN, to insert a string in the middle you have to wrap it a SPAN like we did above.*

I hope you are starting to see a pattern here. Hyperstack components determine what to display based on the `state` of some objects. External events, such as mouse clicks, the arrival of new data from the server, and even timers update the `state`. Hyperstack recomputes whatever portion of the display depends on the `state` so that the display is always in sync with the `state`. In our case the objects are the Todo model and its associated records, which have a number of associated internal `states`.

By the way, you don't have to use Models to have states. We will see later that states can be as simple as boolean instance variables.

## Chapter 6: Routing

Now that Todos can be *completed* or *active*, we would like our user to be able display either "all" Todos, only "completed" Todos, or "active" (or incomplete) Todos. We want our URL to reflect which filter is currently being displayed. So `/all` will display all todos, `/completed` will display the completed Todos, and of course `/active` will display only active (or incomplete) Todos. We would also like the root url `/` to be treated as `/all`

To achieve this we first need to be able to *scope* (or filter) the Todo Model. So let's edit the Todo model file so it looks like this:

```ruby
# app/hyperstack/models/todo.rb
class Todo < ApplicationRecord
  scope :completed, -> () { where(completed: true)  }
  scope :active,    -> () { where(completed: false) }
end
```

Now we can say `Todo.all`, `Todo.completed`, and `Todo.active`, and get the desired subset of Todos. You might want to try it now in the rails console. *Note: you will have to do a `reload!` to load the changes to the Model.*

We would like the URL of our App to reflect which of these *filters* is being displayed. So if we load

* `/all` we want the Todo.all scope to be run;
* `/completed` we want the Todo.completed scope to be run;
* `/active` we want the Todo.active scope to be run;
* `/` (by itself) then we should redirect to `/all`.

Having the application display different data (or whole different components) based on the URL is called routing.

Lets change `App` to look like this:

```ruby
# app/hyperstack/components/app.rb
class App < HyperComponent
  include Hyperstack::Router
  render do
    SECTION do
      Header()
      Route('/', exact: true) { Redirect('/all') }
      Route('/:scope', mounts: Index)
      Footer()
    end
  end
end
```

and the `Index` component to look like this:

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  include Hyperstack::Router::Helpers
  render(SECTION) do
    UL do
      Todo.send(match.params[:scope]).each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end
```

Lets walk through the changes:

* We mount the `Header` components as before.
* We then check to see if the current route exactly matches `/` and if it does, redirect to `/all`.
* Then instead of directly mounting the `Index` component, we *route* to it based on the URL.  In this case if the url must look like `/xxx`.
* `Index` now includes (mixes-in) the `Hyperstack::Router::Helpers` module which has methods like `match`.
* Instead of simply enumerating all the Todos, we decide which *scope* to filter using the URL fragment *matched* by `:scope`. &#x20;

Notice the relationship between `Route('/:scope', mounts: Index)` and `match.params[:scope]`:

During routing each `Route` is checked. If it *matches* then the indicated component is mounted, and the match parameters are saved for that component to use.

You should now be able to change the url from `/all`, to `/completed`, to `/active`, and see a different set of Todos. For example if you are displaying the `/active` Todos, you will only see the Todos that are not complete. If you check one of these it will disappear from the list.

> Rails also has the concept of routing, so how do the Rails and Hyperstack routers interact? Have a look at the config/routes.rb file. You will see a line like this:\
> `get '/(*other)', to: 'hyperstack#app'`\
> This is telling Rails to accept all requests and to process them using the `Hyperstack` controller, which will attempt to mount a component named `App` in response to the request. The mounted App component is then responsible for further processing the URL.
>
> For more complex scenarios Hyperstack provides Rails helper methods that can be used to mount components from your controllers, layouts, and views.

## Chapter 7:  Helper Methods, Inline Styling, Active Support and Router Nav Links

Of course we will want to add navigation to move between these routes. We will put the navigation in the footer:

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  def link_item(path)
    A(href: "/#{path}", style: { marginRight: 10 }) { path.camelize }
  end
  render(DIV) do
    link_item(:all)
    link_item(:active)
    link_item(:completed)
  end
end
```

Save the file, and you will now have 3 links, that you will change the path between the three options.

Here is how the changes work:

* Hyperstack is just Ruby, so you are free to use all of Ruby's rich feature set to structure your code. For example the `link_item` method is just a *helper* method to save us some typing.
* The `link_item` method uses the `path` argument to construct an HTML *Anchor* tag.
* Hyperstack comes with a large portion of the Rails active-support library.  For the text of the anchor tag we use the active-support method `camelize`.
* Later we will add proper css classes, but for now we use an inline style.  Notice that the css `margin-right` is written `marginRight`, and that `10px` can be expressed as the integer 10.

Notice that as you click each link the page reloads. **However** what we really want is for the links to simply change the route, without reloading the page.

To make this happen we will *mixin* some router helpers by *including* `HyperRouter::ComponentMethods` inside of class.

Then we can replace the anchor tag with the Router's `NavLink` component:

Change

```ruby
  A(href: "/#{path}", style: { marginRight: 10 }) { path.camelize }
```

to

```ruby
  NavLink("/#{path}", style: { marginRight: 10 }) { path.camelize }
  # note that there is no href key in NavLink
```

Our component should now look like this:

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  include Hyperstack::Router::Helpers
  def link_item(path)
    NavLink("/#{path}", style: { marginRight: 10 }) { path.camelize }
  end
  render(DIV) do
    link_item(:all)
    link_item(:active)
    link_item(:completed)
  end
end
```

After this change you will notice that changing routes *does not* reload the page, and after clicking to different routes, you can use the browsers forward and back buttons.

How does it work? The `NavLink` component reacts to a click just like an anchor tag, but instead of changing the window's URL directly, it updates the *HTML5 history object.* Associated with this history is (hope you guessed it) *state*. So when the history changes it causes any components depending on the state of the URL to be re-rendered.

## Chapter 8: Create a Basic EditItem Component

So far we can mark Todos as completed, delete them, and filter them. Now we create an `EditItem` component so we can change the Todo title.

Add a new component like this:

```ruby
# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  render do
    INPUT(defaultValue: @Todo.title)
    .on(:enter) do |evt|
      @Todo.update(title: evt.target.value)
    end
  end
end
```

Before we use this component let's understand how it works.

* It receives a `todo` param which will be edited by the user;
* The `title` of the todo is displayed as the initial value of the input;
* When the user types the enter key updated.

Now update the `TodoItem` component replacing

```ruby
  SPAN { @Todo.title }
```

with

```ruby
  EditItem(todo: @Todo)
```

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.

## Chapter 9: Adding State to a Component, Defining Custom Events, and a Lifecycle Callback.

This all works, but its hard to use. There is no feed back indicating that a Todo has been saved, and there is no way to cancel after starting to edit. We can make the user interface much nicer by adding *state* (there is that word again) to the `TodoItem`. We will call our state `editing`. If `editing` is true, then we will display the title in a `EditItem` component, otherwise we will display it in a `LABEL` tag. The user will change the state to `editing` by double clicking on the label. When the user saves the Todo, we will change the state of `editing` back to false. Finally we will let the user *cancel* the edit by moving the focus away (the `blur` event) from the `EditItem`. To summarize:

* User double clicks on any Todo title: editing changes to `true`.
* User saves the Todo being edited: editing changes to `false`.
* User changes focus away (`blur`) from the Todo being edited: editing changes to `false`.

In order to accomplish this our `EditItem` component is going to communicate to its parent via two application defined events - `save` and `cancel` .\
Add the following 5 lines to the `EditItem` component like this:

```ruby
# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  triggers :save                             # add
  triggers :cancel                           # add
  after_mount { DOM[dom_node].focus }        # add

  render do
    INPUT(defaultValue: @Todo.title)
    .on(:enter) do |evt|
      @Todo.update(title: evt.target.value)
      save!                                  # add
    end
    .on(:blur) { cancel! }                   # add
  end
end
```

The first two new lines add our custom events.

The next new line uses one of several *Lifecycle Callbacks*. In this case we need to move the focus to the `EditItem` component after is mounted. The `DOM` class is Hyperstack's jQuery wrapper, and `dom_node` is the method that returns the actual dom node where this instance of the component is mounted.

The `save!` line will trigger the save event in the parent component. Notice that the method to trigger a custom event is the name of the event followed by a bang (!).

Finally we add the `blur` event handler and trigger our `cancel` event.

Now we can update our `TodoItem` component to be a little state machine, which will react to three events: `double_click`, `save` and `cancel`.

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI) do
    if @editing
      EditItem(todo: @Todo)
      .on(:save, :cancel) { mutate @editing = false }
    else
      INPUT(type: :checkbox, checked: @Todo.completed)
      .on(:change) { @Todo.update(completed: !@Todo.completed) }
      LABEL { @Todo.title }
      .on(:double_click) { mutate @editing = true }
      A { ' -X-' }
      .on(:click) { @Todo.destroy }
    end
  end
end
```

All states in Hyperstack are simply Ruby instance variables (ivars). Here we use the `@editing` ivar.

We have already used a lot of states that are built into the HyperModel and HyperRouter. The state machines in these complex objects are built out collections of instance variables like `@editing`.

In the `TodoItem` component the value of `@editing ...` controls whether to render the `EditItem` or the INPUT, LABEL, and Anchor tags.

Because `@editing` (like all ivars) starts off as nil, when the `TodoItem` first mounts, it renders the INPUT, LABEL, and Anchor tags. Attached to the label tag is a `double_click` handler which does one thing: *mutates* the component's state setting `@editing` to true. This then causes the component to re-render, and now instead of the three tags, we will render the `EditItem` component.

Attached to the `EditItem` component is the `save` and `cancel` handler (which is shared between the two events) that *mutates* the component's state, setting `@editing` back to false.

Using and changing state in a component is a simple as reading or changing the value of some instance variables. The only caveat is that whenever you want to change a state variable whether its a simple assignment or changing the internal value of a complex structure like a hash or array you use the `mutate` method to signal Hyperstack that that state is changing.

## Chapter 10: Using EditItem to create new Todos

Our `EditItem` component has a good robust interface. It takes a Todo, and lets the user edit the title, and then either save or cancel, using two custom events to communicate back outwards.

Because of this we can easily reuse `EditItem` to create new Todos. Not only does this save us time, but it also insures that the user interface acts consistently.

Update the `Header` component to use `EditItem` like this:

```ruby
# app/hyperstack/components/header.
class Header < HyperComponent
  before_mount { @new_todo = Todo.new }
  render(HEADER) do
    EditItem(todo: @new_todo)
    .on(:save) { mutate @new_todo = Todo.new }
  end
end
```

What we have done is initialize an instance variable `@new_todo` to a new unsaved `Todo` item in the `before_mount` lifecycle method.

Then we pass the value `@new_todo` to EditItem, and when it is saved, we generate another new Todo and save it in the `new_todo` state variable.

When `Header`'s state is mutated, it will cause a re-render of the Header, which will then pass the new value of `@new_todo`, to `EditItem`, causing that component to also re-render.

We don't care if the user cancels the edit, so we simply don't provide a `:cancel` event handler.

Once the code is added a new input box will appear at the top of the window, and when you type enter a new Todo will be added to the list.

However you will notice that the value of new Todo input box does not clear. This is subtle problem but it's easy to fix.

React treats the `INPUT` tag's `defaultValue` specially. It is only read when the `INPUT` is first mounted, so it *does not react* to changes like normal parameters. Our `Header` component does pass in new Todo records, but even though they are changing React *does not* update the INPUT.

React has a special param called `key`. React uses this to uniquely identify mounted components. It is used to keep track of lists of components, it can also used in this case to indicate that the component needs to be remounted by changing the value of key.

All objects in Hyperstack respond to the `to_key` method which will return a suitable unique key id, so all we have to pass `@Todo` as the key param it this will insure that as `@Todo` changes, we will re-initialize the `INPUT` tag.

```ruby
  ...
  INPUT(defaultValue: @Todo.title, key: @Todo) # add the special key param
  ...
```

## Chapter 11: Adding Styling

We are just going to steal the style sheet from the benchmark Todo app, and add it to our assets.

**Go grab the file in this repo here:** <https://github.com/hyperstack-org/hyperstack/blob/edge/docs/tutorial/assets/todo.css> and copy it to a new file called `todo.css` in the `app/assets/stylesheets/` directory.

You will have to refresh the page after changing the style sheet.

Now its a matter of updating the css classes which are passed to components via the `class` parameter.

Let's start with the `App` component. With styling it will look like this:

```ruby
# app/hyperstack/components/app.rb
class App < Hyperstack::Router
  history :browser
  route do
    SECTION(class: 'todo-app') do # add the class param
      Header()
      Route('/:scope', mounts: Index)
      Footer()
    end
  end
end
```

The `Footer` components needs have a `UL` added to hold the links nicely, and we can also use the `NavLinks` `active_class` param to highlight the link that is currently active:

```ruby
# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  include Hyperstack::Router::Helpers
  def link_item(path)
    # wrap the NavLink in a LI and
    # tell the NavLink to change the class to :selected when
    # the current (active) path equals the NavLink's path.
    LI { NavLink("/#{path}", active_class: :selected) { path.camelize } }
  end
  render(DIV, class: :footer) do   # add class
    UL(class: :filters) do         # wrap links in a UL
      link_item(:all)
      link_item(:active)
      link_item(:completed)
    end
  end
end
```

For the Index component just add the `main` and `todo-list` classes.

```ruby
# app/hyperstack/components/index.rb
class Index < HyperComponent
  include Hyperstack::Router::Helpers
  render(SECTION, class: :main) do         # add class main
    UL(class: 'todo-list') do              # add class todo-list
      Todo.send(match.params[:scope]).each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end
```

For the EditItem component we want the parent to pass any html parameters such as `class` along to the INPUT tag. We do this by adding the special `others` param that will collect any extra params, we then pass it along in to the INPUT tag. Hyperstack will take care of merging all the params together sensibly.

```ruby
# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  triggers :save                             
  triggers :cancel    
  others   :etc  # can be named anything you want                       
  after_mount { DOM[dom_node].focus }        
  render do
    INPUT(@Etc, defaultValue: @Todo.title, key: @Todo)
    .on(:enter) do |evt|
      @Todo.update(title: evt.target.value)
      save!
    end
    .on(:blur) { cancel! }                   
  end
end
```

Now we can add classes to the TodoItem's list-item, input, anchor tags, and to the `EditItem` component:

```ruby
# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI, class: 'todo-item') do # add the todo-item class
    if @editing
      EditItem(class: :edit, todo: @Todo)  # add the edit class
      .on(:save, :cancel) { mutate @editing = false }
    else
      INPUT(type: :checkbox, class: :toggle, checked: @Todo.completed) # add the toggle class
      .on(:change) { @Todo.update(completed: !@Todo.completed) }
      LABEL { @Todo.title }
      .on(:double_click) { mutate @editing = true }
      A(class: :destroy) # add the destroy class and remove the -X- placeholder
      .on(:click) { @Todo.destroy }
    end
  end
end
```

In the Header we can send a different class to the `EditItem` component. While we are at it we will add the `H1 { 'todos' }` hero unit.

```ruby
# app/hyperstack/components/header.
class Header < HyperComponent
  before_mount { @new_todo = Todo.new }
  render(HEADER, class: :header) do                   # add the 'header' class
    H1 { 'todos' }                                    # Add the hero unit.
    EditItem(class: 'new-todo', todo: @new_todo) # add 'new-todo' class
    .on(:save) { mutate @new_todo = Todo.new }
  end
end
# app/hyperstack/components/header.
class Header < HyperComponent
  before_mount { @new_todo = Todo.new }
  render(HEADER) do
    EditItem(todo: @new_todo)
    .on(:save) { mutate @new_todo = Todo.new }
  end
end
```

At this point your Todo App should be properly styled.

## Chapter 12: Other Features

* **Show How Many Items Left In Footer**\
  This is just a span that we add before the link tags list in the Footer component:

  ```ruby
  ...
  render(DIV, class: :footer) do
    SPAN(class: 'todo-count') do
      "#{Todo.active.count} item#{'s' if Todo.active.count != 1} left"
    end
    UL(class: :filters) do
    ...
  ```
* **Add 'placeholder' Text To Edit Item**\
  EditItem should display a meaningful placeholder hint if the title is blank:

  ```ruby
    ...
    INPUT(@Etc, placeholder: 'What is left to do today?',
                defaultValue: @Todo.title, key: @Todo)
    .on(:enter) do |evt| ...
    ...
  ```
* **Don't Show the Footer If There are No Todos**\
  In the `App` component add a *guard* so that we won't show the Footer if there are no Todos:

  ```ruby
  ...
      Footer() unless Todo.count.zero?
  ...
  ```

Congratulations! you have completed the tutorial.

## Summary

You have built a small but feature rich full stack Todo application in less than 100 lines of code:

```
SLOC  
--------------  
App:        11  
Header:      8
Index:      10  
TodoItem:   16  
EditItem:   16  
Footer:     16  
Todo Model:  4  
Rails Route: 2  
--------------  
Total:      83
```

The complete application is shown here:

```ruby
# app/hyperstack/components/app.rb
class App < HyperComponent
  include Hyperstack::Router
  render do
    SECTION(class: 'todo-app') do
      Header()
      Route('/', exact: true) { Redirect('/all') }
      Route('/:scope', mounts: Index)
      Footer() unless Todo.count.zero?
    end
  end
end

# app/hyperstack/components/header.
class Header < HyperComponent
  before_mount { @new_todo = Todo.new }
  render(HEADER, class: :header) do
    H1 { 'todos' }
    EditItem(class: 'new-todo', todo: @new_todo)
    .on(:save) { mutate @new_todo = Todo.new }
  end
end

# app/hyperstack/components/index.rb
class Index < HyperComponent
  include Hyperstack::Router::Helpers
  render(SECTION, class: :main) do
    UL(class: 'todo-list') do
      Todo.send(match.params[:scope]).each do |todo|
        TodoItem(todo: todo)
      end
    end
  end
end

# app/hyperstack/components/footer.rb
class Footer < HyperComponent
  include Hyperstack::Router::Helpers
  def link_item(path)
    LI { NavLink("/#{path}", active_class: :selected) { path.camelize } }
  end
  render(DIV, class: :footer) do
    SPAN(class: 'todo-count') do
      "#{Todo.active.count} item#{'s' if Todo.active.count != 1} left"
    end
    UL(class: :filters) do
      link_item(:all)
      link_item(:active)
      link_item(:completed)
    end
  end
end

# app/hyperstack/components/todo_item.rb
class TodoItem < HyperComponent
  param :todo
  render(LI, class: 'todo-item') do
    if @editing
      EditItem(class: :edit, todo: @Todo)  # add the edit class
      .on(:save, :cancel) { mutate @editing = false }
    else
      INPUT(type: :checkbox, class: :toggle, checked: @Todo.completed) # add the toggle class
      .on(:change) { @Todo.update(completed: !@Todo.completed) }
      LABEL { @Todo.title }
      .on(:double_click) { mutate @editing = true }
      A(class: :destroy) # add the destroy class and remove the -X- placeholder
      .on(:click) { @Todo.destroy }
    end
  end
end

# app/hyperstack/components/edit_item.rb
class EditItem < HyperComponent
  param :todo
  triggers :save
  triggers :cancel
  others   :etc
  after_mount { DOM[dom_node].focus }
  render do
    INPUT(@Etc, placeholder: 'What is left to do today?',
                defaultValue: @Todo.title, key: @Todo)
    .on(:enter) do |evt|
      @Todo.update(title: evt.target.value)
      save!
    end
    .on(:blur) { cancel! }
  end
end

# app/hyperstack/models/todo.rb
class Todo < ApplicationRecord
  scope :completed, -> () { where(completed: true)  }
  scope :active,    -> () { where(completed: false) }
end

# config/routes.rb
Rails.application.routes.draw do
  mount Hyperstack::Engine => '/hyperstack'
  get '/(*other)', to: 'hyperstack#app'
end
```

## General troubleshooting

1: Wait. On initial boot it can take several minutes to pre-compile all the system assets.

2: Make sure to save (or better yet do a git commit) after every instruction so that you can backtrack

3: Its possible to get things so messed up the hot-reloader will not work. Restart the server and reload the browser.

4: Reach out to us on Gitter, we are always happy to help get you onboarded!


# Community

## Community and support

Hyperstack is supported by a friendly, helpful community, both for users, and contributors. We welcome new people, please reach out and say hello.

* [Join](https://join.slack.com/t/hyperstack-org/shared_invite/enQtNTg4NTI5NzQyNTYyLWQ4YTZlMGU0OGIxMDQzZGIxMjNlOGY5MjRhOTdlMWUzZWYyMTMzYWJkNTZmZDRhMDEzODA0NWRkMDM4MjdmNDE) our Slack group
* After you have joined there is a shortcut at <https://hyperstack.org/slack>

## StackOverflow questions

Please ask technical questions on StackOverflow as the answers help people in the future. We use the `hyperstack` tag, but also add `ruby-on-rails`, `ruby` and `react-js` tags to get this project exposed to a broader community.

* Please ask questions here: <https://hyperstack.org/question>
* All the `hyperstack` tagged questions are here: <https://hyperstack.org/questions>

## Github issues

If you find a bug please create an issue or better still a PR! There are also a list of issues marked as "good first issue"

* Our Github issues are here: <https://github.com/hyperstack-org/hyperstack/issues>

## Improving the docs

* We always welcome any improvements to the docs, so please issue a PR from the docs pages&#x20;

## Write a tutorial or blog

* More than anything, this project needs promotion. If you like this project there is no greater way to show it than write about it and broadcast it to the world. Writing a tutorial is a fantastic way of learning as well.&#x20;


