Notes

Blocks in Ruby

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

The following code in Ruby:

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

is roughly equivilent to this Javascript

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

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

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:

The HyperComponent Base Class

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

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...

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

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.

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 Procs

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

Ruby has several ways to create procs:

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...

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

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.

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:

I'm sorry I can't resist. Really?

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:

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:

The Enter Event

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

Last updated

Was this helpful?