easy_flow 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/models/easy_flow/compare.rb +25 -0
- data/lib/easy_flow/engine.rb +1 -0
- data/lib/easy_flow/version.rb +1 -1
- data/the_local/agents/easy_flow-develop.md +13 -9
- data/the_local/agents/easy_flow-info.md +13 -8
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ac79c8ce4bb5e4684bffa9ae4e01b03d7eedfc7bcea71d942a42001fdbd1b3e
|
|
4
|
+
data.tar.gz: 36dcb39f97780d9132bcd71a5a7dd3a335859d88ce0623dd4610ed1882e2b1e9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a07323057c7278472b1233247d518ccee87aa7baf27ec5e53f1b747345b3c7909c3be28fde2fbaf43871655627efc163461d3aa683fa2548dc27b4f8bb322670
|
|
7
|
+
data.tar.gz: db782393e3af4feef0e360158d4702fb250c3d3251046e65ebe03256a153e23a649814cef0cb7d0db5591d1ba14cef841a41837b98069a92378d8eaaa2a43754
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module EasyFlow
|
|
2
|
+
class Compare
|
|
3
|
+
include Step
|
|
4
|
+
|
|
5
|
+
COMPARISONS = { "more than" => :>, "less than" => :<, "at least" => :>=, "at most" => :<= }.freeze
|
|
6
|
+
|
|
7
|
+
step_name "Compare"
|
|
8
|
+
|
|
9
|
+
setting :step, type: :previous_step
|
|
10
|
+
setting :output, outputs_of: :step
|
|
11
|
+
setting :comparison, type: :select, options: COMPARISONS.keys, required: true
|
|
12
|
+
setting :amount, type: :float, required: true
|
|
13
|
+
|
|
14
|
+
output :result, type: :boolean, values: [ true, false ]
|
|
15
|
+
|
|
16
|
+
def route(node, state)
|
|
17
|
+
answer = state[node.config["step"]]
|
|
18
|
+
answer = answer[node.config["output"]] if answer.is_a?(Hash)
|
|
19
|
+
number = Float(answer.to_s, exception: false)
|
|
20
|
+
return false if number.nil?
|
|
21
|
+
|
|
22
|
+
number.public_send(COMPARISONS.fetch(node.config["comparison"]), node.config["amount"])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/easy_flow/engine.rb
CHANGED
data/lib/easy_flow/version.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: easy_flow-develop
|
|
3
|
-
description: Use PROACTIVELY for adding a step type to easy_flow flows (a step that asks the visitor something, computes a value from earlier answers, or picks the next branch), serving a host's flows from the app's own controller and routes, acting when a visitor finishes a flow, and reading a run's recorded answers and question labels — MUST BE USED instead of hand-rolling questionnaire steps, branching logic, flow controllers or answer lookups.
|
|
3
|
+
description: Use PROACTIVELY for adding a step type to easy_flow flows (a step that asks the visitor something, computes a value from earlier answers, or picks the next branch), serving a host's flows from the app's own controller and routes, acting when a visitor finishes a flow, and reading a run's recorded answers and question labels — MUST BE USED instead of hand-rolling questionnaire steps, branching logic, number comparisons, flow controllers or answer lookups.
|
|
4
4
|
tools: Read, Write, Edit, Grep
|
|
5
5
|
scope: guided flows — versioned documents of steps and the connections between them, drawn on a canvas by an admin and run by a visitor one step at a time, with step types the host registers
|
|
6
6
|
---
|
|
@@ -9,7 +9,7 @@ This local follows the steps below exactly and invents none. Where a step names
|
|
|
9
9
|
|
|
10
10
|
## What easy_flow is
|
|
11
11
|
|
|
12
|
-
A Rails engine for flows an admin draws on a canvas and a visitor runs one step at a time. Each step is an instance of a step type
|
|
12
|
+
A Rails engine for flows an admin draws on a canvas and a visitor runs one step at a time. Each step is an instance of a step type. The engine ships six: start (`:start`), end (`:terminal`), question (`:question`, a question with a list of answers), and three that pick a branch from an earlier answer with no code — condition (`:condition`, is or is not a chosen value), switch (`:switch`, follows the connection labelled with the answer) and compare (`:compare`, reads the answer as a number and checks it by more than, less than, at least or at most against an amount). Before writing a step type to branch on an answer or a number, ask the developer whether an admin placing one of those three on the canvas is enough. Use this local when the app needs a step type of its own, needs a host's flows on its own pages with its own behaviour when a visitor finishes, or needs to read what a visitor answered. It assumes easy_flow is already installed and a host is declared; if not, hand off to `easy_flow-install` first.
|
|
13
13
|
|
|
14
14
|
## Interface
|
|
15
15
|
|
|
@@ -29,8 +29,8 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
29
29
|
- It asks the visitor for input — declare `awaits_input`.
|
|
30
30
|
- It computes a value from earlier answers with no visitor input — define `process`.
|
|
31
31
|
- It only picks which connection to follow — define `route`.
|
|
32
|
-
A type may both `process` and `route`. A type that does none of the three is
|
|
33
|
-
2. Create the class in the app, for example `app/models/flow_steps/rating.rb`. The class name, underscored, is the type's id (`Rating` becomes `:rating`), and that id is stored in every flow that uses it, so it must not change after admins start using the type
|
|
32
|
+
A type may both `process` and `route`. A type that does none of the three is passed through without stopping when a visitor reaches it.
|
|
33
|
+
2. Create the class in the app, for example `app/models/flow_steps/rating.rb`. The class name, underscored, is the type's id (`Rating` becomes `:rating`), and that id is stored in every flow that uses it, so it must not change after admins start using the type. It must not be one of the built-in ids `start`, `terminal`, `question`, `condition`, `switch` or `compare`:
|
|
34
34
|
|
|
35
35
|
```ruby
|
|
36
36
|
module FlowSteps
|
|
@@ -74,8 +74,8 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
74
74
|
A step whose type is not registered is neither shown nor run as that type.
|
|
75
75
|
4. Use these words to declare the type. Each is called once at class level (or inside the `EasyFlow.step` block):
|
|
76
76
|
- `step_name "<label>"` — the name admins see on the canvas. Defaults to the id.
|
|
77
|
-
- `setting :name, type:, label:, options:, required:, limit:, check:, from:, outputs_of:` — a field the admin fills in on the canvas. `type` is one of `:string`, `:integer`, `:float`, `:boolean`, `:select`, `:multi_select`, `:previous_step`, `:from_step`, `:list`. A `:select` or `:multi_select` must pass `options:`, or boot raises
|
|
78
|
-
- `output :name, type:, label:, values:, from:` — a value the step records. `type` is one of `:string`, `:integer`, `:float`, `:boolean`, or boot raises `EasyFlow::UnknownOutputType`. `values:` is an array or a lambda taking the node, listing the values the output can take; the canvas offers these as the connections leaving the step. `from: :<setting>` takes the values from the step chosen in that setting.
|
|
77
|
+
- `setting :name, type:, label:, options:, required:, limit:, check:, from:, outputs_of:` — a field the admin fills in on the canvas. `type` is one of `:string`, `:integer`, `:float`, `:boolean`, `:select`, `:multi_select`, `:previous_step`, `:from_step`, `:list`, or boot raises `EasyFlow::UnknownFieldType`. A `:select` or `:multi_select` must pass `options:`, or boot raises the same error. A `:list` must take a block of `setting` calls describing one entry. `:previous_step` lets the admin pick an earlier step, and is always required. `outputs_of: :<setting>` offers the outputs of the step chosen in that setting, and `from: :<setting>` offers the values of the output chosen in that setting; either one makes the type `:from_step`. `limit:` is the most values a `:multi_select` takes. `check:` is a lambda given the value that returns an error message, or `nil` when the value is acceptable. `label:` defaults to the name humanized.
|
|
78
|
+
- `output :name, type:, label:, values:, from:` — a value the step records. `type` is one of `:string`, `:integer`, `:float`, `:boolean`, or boot raises `EasyFlow::UnknownOutputType`. `values:` is an array or a lambda taking the node, listing the values the output can take; the canvas offers these as the connections leaving the step, so a type that routes must declare them. `from: :<setting>` takes the values from the step chosen in that setting.
|
|
79
79
|
- `names_by :setting` or `names_by { |node| ... }` — what the step is called on the canvas, from a setting or computed.
|
|
80
80
|
- `awaits_input` — the visitor is shown this step and must answer it.
|
|
81
81
|
- `ends_here` / `begins_here` — marks the type as an end or a start of a flow.
|
|
@@ -96,7 +96,8 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
96
96
|
- `node` has `id`, `type` and `config`; `config` is a hash of the admin's settings with string keys.
|
|
97
97
|
- `state` is the answers recorded so far, keyed by step id as strings.
|
|
98
98
|
- `process` returns the value recorded under this step's id. It runs as soon as a visitor reaches the step, before the next step is shown.
|
|
99
|
-
- `
|
|
99
|
+
- A type that declares more than one `output` returns a hash from `process`, keyed by each output's name as a string. A later compare step reads the output the admin picks from that hash.
|
|
100
|
+
- `route` returns the value that picks the connection to follow; it is compared as a string with the value each leaving connection is labelled with, so `false` follows the connection labelled `false`. Returning `nil` follows the first connection. A route that returns `true` or `false` declares `output :result, type: :boolean, values: [true, false]`.
|
|
100
101
|
6. For a type that awaits input, write the partial named in `drawn_by`, for example `app/views/flow_steps/_rating.html.erb`. It receives the display object as `step`. It renders only the input, since the page supplies the form, the Next button and the Back button. The input must be named `answers[<step id>]`, or the answer is not recorded:
|
|
101
102
|
|
|
102
103
|
```erb
|
|
@@ -104,6 +105,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
104
105
|
<%= number_field_tag "answers[#{step.id}]", nil, in: 1..step.scale %>
|
|
105
106
|
```
|
|
106
107
|
|
|
108
|
+
An answer is recorded as the string the visitor submitted. A compare step still reads a typed answer such as `"12"` as the number it spells, and an answer that is missing or is not a number makes it follow its `false` connection.
|
|
107
109
|
7. Restart the server, open a flow on the canvas and check the type is offered, its settings show, and a preview walks through it.
|
|
108
110
|
|
|
109
111
|
### Serve a host's flows from the app's own controller
|
|
@@ -136,8 +138,8 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
136
138
|
|
|
137
139
|
The controller inherits from the base controller set at install, uses the host's layout, visitor authorization and refusal methods, and only finds flows that belong to the named host. Pages it does not override use the engine's own views.
|
|
138
140
|
4. Override only the private methods the developer's answers call for:
|
|
139
|
-
- `finished(answers, run)` — called when the visitor reaches the end. `answers` is the answers on the path taken, keyed by step id as symbols. `run` is the stored `EasyFlow::Run`, or `nil` when the flow
|
|
140
|
-
- `start_run(flow)` — creates the run when a visitor starts a flow
|
|
141
|
+
- `finished(answers, run)` — called when the visitor reaches the end. `answers` is the answers on the path taken, keyed by step id as symbols. `run` is the stored `EasyFlow::Run`, or `nil` when the admin set the flow to save nothing. A flow the admin set to save on finish gets its run created at this point. It must render or redirect. Default: the engine's completion page.
|
|
142
|
+
- `start_run(flow)` — creates the run when a visitor starts a flow the admin set to save each step. Call `super` and change the run it returns, for example to set its `owner` or `label`.
|
|
141
143
|
- `runner_for(definition)` — returns the runner used for each step. Return a subclass of `EasyFlow::QuestionRunner` to change what the step and completion pages read from it.
|
|
142
144
|
5. Visit `/<path>/<slug>` for a published flow and walk it to the end.
|
|
143
145
|
|
|
@@ -167,7 +169,9 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
167
169
|
## Conventions
|
|
168
170
|
|
|
169
171
|
- A step type's id comes from its class name or the id passed to `EasyFlow.step`, and it is stored in flow documents, so renaming the class or id breaks every flow that uses it.
|
|
172
|
+
- Never give a step type one of the built-in ids: `start`, `terminal`, `question`, `condition`, `switch`, `compare`.
|
|
170
173
|
- Register class-based step types inside `to_prepare`. A type registered anywhere else is lost on code reload in development.
|
|
174
|
+
- A type that routes declares the values its output takes, or the canvas offers no connections to label.
|
|
171
175
|
- Always read a run against `run.pinned_definition`, never the flow's live version, since a run keeps the version it started on after a new one is published.
|
|
172
176
|
- Always look flows and runs up through a host.
|
|
173
177
|
- A step's input field is named `answers[<step id>]`. Any other name is ignored.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: easy_flow-info
|
|
3
|
-
description: Use to learn what easy_flow offers — guided flows an admin draws on a canvas and a visitor runs one step at a time, versioned documents of steps and connections, hosts, runs, and step types the host app registers.
|
|
3
|
+
description: Use to learn what easy_flow offers — guided flows an admin draws on a canvas and a visitor runs one step at a time, versioned documents of steps and connections, hosts, runs, the built-in step types including branching on an answer or comparing a number, and step types the host app registers.
|
|
4
4
|
tools: Read
|
|
5
5
|
scope: guided flows — versioned documents of steps and the connections between them, drawn on a canvas by an admin and run by a visitor one step at a time, with step types the host registers
|
|
6
6
|
---
|
|
@@ -11,32 +11,37 @@ This local explains easy_flow and the words it uses. It makes no changes and giv
|
|
|
11
11
|
|
|
12
12
|
easy_flow is a Rails engine for guided, branching flows. An admin builds a flow on a canvas by placing steps and connecting them, previews it, and publishes it. A visitor then walks the published flow one step at a time, and each answer decides which step comes next.
|
|
13
13
|
|
|
14
|
-
Reach for it when an app needs a questionnaire, an intake form, or any decision path that an admin should be able to change without a deploy. The engine ships
|
|
14
|
+
Reach for it when an app needs a questionnaire, an intake form, or any decision path that an admin should be able to change without a deploy. The engine ships a start step, an end step, a question step, and three steps that pick a branch from earlier answers. Anything else a flow needs to ask or do is a step type the app declares itself.
|
|
15
15
|
|
|
16
16
|
## Interface
|
|
17
17
|
|
|
18
18
|
easy_flow declares no commands of its own for this local. Its surface is split between the other two:
|
|
19
19
|
|
|
20
|
-
- **easy_flow-install** owns putting the engine into an app: its migrations, mounting it, choosing the controller it inherits from, naming hosts, choosing the
|
|
20
|
+
- **easy_flow-install** owns putting the engine into an app: its migrations, mounting it, choosing the controller it inherits from, naming hosts, choosing the default step drawing, the flow checks, and the admin pages.
|
|
21
21
|
- **easy_flow-develop** owns building on it: declaring and registering step types, serving a host's flows from the app's own controllers and routes, and reading a visitor's run and answers.
|
|
22
22
|
|
|
23
23
|
## How to use it
|
|
24
24
|
|
|
25
25
|
- To get easy_flow running in an app, or to change how it is configured, use **easy_flow-install**.
|
|
26
26
|
- To add a step type, put a flow on the app's own pages, or act on what a visitor answered, use **easy_flow-develop**.
|
|
27
|
+
- To branch a flow on an answer or on a number the visitor gave, no code is needed: an admin places one of the built-in branching steps on the canvas.
|
|
27
28
|
- If the question is only what a word below means, this page is the answer.
|
|
28
29
|
|
|
29
30
|
## Conventions
|
|
30
31
|
|
|
31
|
-
- **Flow** — one guided path, found by its slug. It holds a working document the admin edits and a list of versions.
|
|
32
|
+
- **Flow** — one guided path, found by its slug within its host. It holds a working document the admin edits and a list of versions.
|
|
32
33
|
- **Document** — the flow's content: its steps (nodes), the connections between them (edges), a headline and a slug.
|
|
33
34
|
- **Version** — a numbered snapshot of the document. A version is a draft until it is published, and a flow has at most one live version at a time.
|
|
34
35
|
- **Canvas** — the admin screen where steps are added, configured, moved, removed and connected, with undo and redo. Publishing happens there.
|
|
35
36
|
- **Preview** — an admin walking the current flow without starting a stored run.
|
|
36
|
-
- **Step type** — what a kind of step is: its display name, its settings (the fields an admin fills in), its outputs (the values it records), and whether it waits for the visitor or acts on its own. A step that acts on its own
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
37
|
+
- **Step type** — what a kind of step is: its display name, its settings (the fields an admin fills in), its outputs (the values it records), and whether it waits for the visitor or acts on its own. A step that acts on its own may record a value worked out from the answers so far, pick which connection to follow, or both.
|
|
38
|
+
- **Start** and **End** — the built-in step types that begin and finish a flow.
|
|
39
|
+
- **Question** — the built-in step type that asks the visitor: a question text and a list of answers, each with a value, a label and a weight.
|
|
40
|
+
- **Condition** — a built-in branching step that checks whether an earlier step's answer is, or is not, a chosen value, and follows the true or the false connection.
|
|
41
|
+
- **Switch** — a built-in branching step that follows the connection labelled with an earlier step's answer.
|
|
42
|
+
- **Compare** — a built-in branching step that reads an earlier step's answer as a number and checks it against an amount by more than, less than, at least or at most, then follows the true or the false connection. When the earlier step recorded several outputs, the admin picks which one. An answer that is missing or is not a number decides false.
|
|
43
|
+
- **Registry** — the list of step types the app has registered, alongside the built-in ones. A step whose type is not registered is not shown or run as that type.
|
|
39
44
|
- **Host** — a named part of the app that owns a set of flows. A host sets the visitor layout and the admin layout, how admins are authenticated, how visitors are authorized, and how a refusal is answered. Flows are always looked up through a host, so one host never sees another's flows.
|
|
40
45
|
- **Run** — one visitor's pass through a flow. A run is pinned to the version that was live when it started, so publishing a new version does not change a run already under way. It records each answer by step id, and going back discards the last answer on the path.
|
|
41
46
|
- **Answers** — the recorded state of a run, keyed by step id. The next step is always worked out from these answers and the connections in the pinned version.
|
|
42
|
-
- **Checks** —
|
|
47
|
+
- **Checks** — warnings on a flow's shape: an answer value no connection routes, a path nothing follows, and a step that leads nowhere. The engine turns all three on by default.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: easy_flow
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- tylercschneider
|
|
@@ -90,6 +90,7 @@ files:
|
|
|
90
90
|
- app/models/easy_flow/canvas.rb
|
|
91
91
|
- app/models/easy_flow/change.rb
|
|
92
92
|
- app/models/easy_flow/choice.rb
|
|
93
|
+
- app/models/easy_flow/compare.rb
|
|
93
94
|
- app/models/easy_flow/condition.rb
|
|
94
95
|
- app/models/easy_flow/definition.rb
|
|
95
96
|
- app/models/easy_flow/digest.rb
|