Flows

The Flow class is a way of writing a module of methods that operates on some
encapsulated object. You might call it a
mediator. We’ll call the
encapsulated object the contained object in this guide.

Typically we’ll use flows to wrap the request object within Lapis, but it’s not
a requirement and you can use any Lua object. The flow will proxy method calls
and field reads and assignments back to the contained object.

If this explanation is confusing, don’t worry. It’s easier to understand a flow
in example. We’ll use the Flow class standalone to demonstrate how it works.

You can think of a flow of a collection of methods that are designed to operate
on a certain kind of object. Why would we use a flow instead of just making
these methods part of the objects class? A flow lets you encapsulate logic into
a separate namespace. Instead of having classes with many methods, you split
apart your methods into flows and leave the class with a smaller
implementation.

Assigning Fields Within a Flow

If you assign to self in a flow it is saved on the flow instance by default.
This can be used for private data specific to that flow. A good example might
be caching the result of an expensive method call.

If you want assignments on self to be sent back to the original class then
you can use expose_assigns. It’s a class property that tells the flow how to
handle assignments to self.

expose_assigns can take two types of values:

true – all assignments are proxied back to the contained object

An array of strings – any field name contained in this array is proxied back to the object

Accessing The Contained Object

The contained object is stored on self with the name _ (an underscore). You
should avoid writing to this field since the flow expects it to exist.

Organizing Your Application With Flows

in lapis, an application class is where you define routes and your request
logic. since there are so many responsibilities it easy for an applicatoin
class to get too large to maintain. a good way of separating concerns is to use
flows. In this case, the contained object will be the request instance. You’ll
call the flow from within your application. Because this is a common pattern,
there’s a flow method on the request object that makes instantiating flows
easy.

In this example we declare a flow class for handling logging in and registering
on a website. From our applicaton we call the flow: