easy_flow 0.19.0 → 0.20.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e277531505d578e7a66331a93c7af61f08d0558bed385af31d173ce500fadf1
4
- data.tar.gz: 2a9b83f04a28d3831ae1786766849adb73a44b91d828d6e044d751fd223d1ebf
3
+ metadata.gz: 9f82c451744e7908c5f98dc0398363d373894a2635280494a7939186373cbe27
4
+ data.tar.gz: 393c50e4c09189c33f1ff57f64fc2b5c3e5d13b40d0ebca204ffbf5d620c6418
5
5
  SHA512:
6
- metadata.gz: b4df662a23036aa6b8d70253e980b096dca08f4fad0359cc1b6fc14c31328b70efd77e321c1bb1f7d19476dc215d50ed37157c0d5749893901957c3905bc362f
7
- data.tar.gz: f36528a6ea1f1b75c2d76386bf55af3ab1548468590aeb03a0a130f0407f89cf7539e86d170a4bb7ed522a99c9ff120ef93d1b0f00070ffb85f99c6edf8489cc
6
+ metadata.gz: 021def99dc4c41c8ec14d6ea64b55c42d02d683336119822e5eaa326b31f3781dd84b3e7df6bd48faf59b89adbb3de7cfdf6f844cf2bf832639f408a1dfa7c36
7
+ data.tar.gz: 0365723b91965fe7a42b2a57cc906be4881cbb78c40420879c1245035fb30a0b7162252b31c81d975161d302404998e7de6e459323219174f247fc1a5fa49d80
@@ -33,6 +33,7 @@ module EasyFlow
33
33
 
34
34
  def ended
35
35
  parent = @run.parent_run or return
36
+ return if @run.stopped_on_loop
36
37
  return if parent.recorded.key?(@run.parent_step.to_sym)
37
38
 
38
39
  ending = @run.output || ("ended" if chose_from_run?(parent))
@@ -1,3 +1,3 @@
1
1
  module EasyFlow
2
- VERSION = "0.19.0"
2
+ VERSION = "0.20.0"
3
3
  end
@@ -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, takes several answers at once, computes a value from earlier answers, records several values under names an admin enters in the step's settings, counts how many times an earlier step was answered so a loop can give up after a number of tries, picks the next branch, or holds the visitor until something outside the flow has happened), branching on whether all or any of several comparisons of earlier answers hold, holding a run until a number of minutes after an earlier answer, the next time of day after it, or a date, branching on the hour, weekday or time an earlier step was completed or on the minutes between two completed steps, reading when each step was completed and when a waiting run will move on, showing a step differently depending on the visitor's stored run, branching on what a visitor ticked on a checklist, moving a paused run on once what it waits for has happened, refusing a blank or invalid answer to a step with a message, offering an admin a step setting whose options are read from the app's own records, letting an admin pick another flow of the same host in a step's settings, adding a step type that starts another flow and works out which flow and version to run from its own settings, adding a step type that starts another flow chosen from the visitor's run, such as its owner or its answers, offering a visitor only the answers to a step that their earlier answers allow, filling in a step that has only one possible answer without asking it, skipping a step that does not apply to a visitor, letting an admin edit a value stored on one of the app's own records from a step's settings on the canvas, serving a host's flows from the app's own controller and routes, starting a visitor's run on a published version of a flow other than the live one, acting when a visitor finishes a flow, acting on the output a visitor's flow ended with, telling whether a run ended at an End step or was stopped by a loop that came back with nothing new answered and at which step, keeping a flow from being published while a step that starts another flow names a flow or version that cannot run or leads back to the flow it sits in, finding the run of another flow that a Flow step started, the run a waiting run is waiting on, and the run that started it, sending a visitor back to the run that started a flow once that flow ends, handling a run whose starting run was removed with its flow, handling a Flow step that cannot start its flow or whose flow ended with no output, taking one file or several from a visitor at a step, showing a step's recorded answer by a label the step type works out, and reading a run's recorded answers and question labels, including every answer ticked on a checklist and every visit's answer when a flow loops back to a question already asked — MUST BE USED instead of hand-rolling questionnaire steps, checkbox lists, file upload steps, branching logic, answer lists filtered by earlier answers, skipped questions, number comparisons, comparisons of two earlier answers, and/or conditions over several comparisons, hard-coded setting options, copying a record's value into a flow and back, answer validation, retry counters, timers or scheduled delays, step completion timestamps, polling or "come back later" pages, 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, takes several answers at once, computes a value from earlier answers, records several values under names an admin enters in the step's settings, counts how many times an earlier step was answered so a loop can give up after a number of tries, picks the next branch, or holds the visitor until something outside the flow has happened), branching on whether all or any of several comparisons of earlier answers hold, holding a run until a number of minutes after an earlier answer, the next time of day after it, or a date, branching on the hour, weekday or time an earlier step was completed or on the minutes between two completed steps, reading when each step was completed and when a waiting run will move on, showing a step differently depending on the visitor's stored run, branching on what a visitor ticked on a checklist, moving a paused run on once what it waits for has happened, refusing a blank or invalid answer to a step with a message, offering an admin a step setting whose options are read from the app's own records, letting an admin pick another flow of the same host in a step's settings, adding a step type that starts another flow and works out which flow and version to run from its own settings, adding a step type that starts another flow chosen from the visitor's run, such as its owner or its answers, offering a visitor only the answers to a step that their earlier answers allow, filling in a step that has only one possible answer without asking it, skipping a step that does not apply to a visitor, letting an admin edit a value stored on one of the app's own records from a step's settings on the canvas, serving a host's flows from the app's own controller and routes, starting a visitor's run on a published version of a flow other than the live one, acting when a visitor finishes a flow, acting on the output a visitor's flow ended with, telling whether a run ended at an End step or was stopped by a loop that came back with nothing new answered and at which step, keeping a flow from being published while a step that starts another flow names a flow or version that cannot run or leads back to the flow it sits in, finding the run of another flow that a Flow step started, the run a waiting run is waiting on, and the run that started it, sending a visitor back to the run that started a flow once that flow ends, handling a run whose starting run was removed with its flow, handling a Flow step that cannot start its flow, whose flow ended with no output, or whose flow was stopped by a loop, taking one file or several from a visitor at a step, showing a step's recorded answer by a label the step type works out, and reading a run's recorded answers and question labels, including every answer ticked on a checklist and every visit's answer when a flow loops back to a question already asked — MUST BE USED instead of hand-rolling questionnaire steps, checkbox lists, file upload steps, branching logic, answer lists filtered by earlier answers, skipped questions, number comparisons, comparisons of two earlier answers, and/or conditions over several comparisons, hard-coded setting options, copying a record's value into a flow and back, answer validation, retry counters, timers or scheduled delays, step completion timestamps, polling or "come back later" pages, 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
  ---
@@ -155,6 +155,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
155
155
  - The flow is found by its id alone, not through the host or owner. Ask the developer which flows the block may name, and look the flow up through the run's flow's host or the run's owner inside the block when it must be limited.
156
156
  - When the block returns `nil`, a blank `flow:`, or the id of no existing flow, `EasyFlow::InnerFlowError` is raised with a message naming the step, such as `The step pick chose no flow to run`, and no run is started. A retired or withdrawn version raises `EasyFlow::InnerFlowError` as for a Flow step, and a blank version number, one naming no version of the flow, or one naming a draft raises `ActiveRecord::RecordInvalid`.
157
157
  - When the started run ends with an output, that output is recorded under the step's id as for a Flow step. When it ends with no output, `"ended"` is recorded instead, and the parent run moves on. A type that routes on what is recorded declares an `output` whose `values:` include `"ended"` beside the outputs the chosen flows can end with. Ask the developer what `"ended"` should lead to.
158
+ - When a loop stops the started run, nothing is recorded, not even `"ended"`, no job is queued, and the parent run stays waiting at the step. See step 5 of "Follow a run into the flow a Flow step started".
158
159
  - A flow set to save on finish or to save nothing, and an admin's preview, keep no stored run, so the block is not called and no run is started.
159
160
 
160
161
  ```ruby
@@ -376,24 +377,29 @@ Use this when a visitor's run reaches a Flow step and the app must take the visi
376
377
  - When the parent run then ends and was itself started by a Flow step, its own output is handed to its parent the same way.
377
378
  - The new run's own `finished` is still called on its visitor's page load. The job does not call `finished` for the parent run, and if the parent run reaches its end, `finished` is called the next time its visitor loads its page.
378
379
  - A visitor who presses Back on the step after a Flow step removes the recorded output, and the parent run waits on the Flow step again. No second run is started, and the parent run moves on again only when the new run's page is loaded or `advance` is called on it.
379
- 4. What holds when the new run ends with no output, which happens when it ends on an End step whose output was left blank, or ends without reaching an End step, and the step that started it is not of a type that declares `chooses_flow_from_run` (for that type, `"ended"` is recorded and the parent run moves on):
380
+ 4. What holds when the new run ends with no output, which happens when it ends on an End step whose output was left blank, or ends without reaching an End step for any reason other than a loop stopping it, and the step that started it is not of a type that declares `chooses_flow_from_run` (for that type, `"ended"` is recorded and the parent run moves on):
380
381
  - Nothing is recorded in the parent run, and the parent run stays at the Flow step showing `Waiting for <name>.` on every page load. Nothing in the engine moves it on.
381
382
  - A job is still queued that fails with `EasyFlow::InnerFlowError` and a message naming the Flow step's id, such as `Nothing was recorded at the Flow step sub, so its run cannot move on`. The job does not move the parent run.
382
383
  - Each later page load of the new run, and each later `advance` on it, queues another job that fails the same way.
383
384
  - What happens to a failed job, such as a retry or a report, is decided by the app's Active Job adapter and error reporting.
384
385
  - The new run's own `finished` is still called on its visitor's page load.
385
- 5. What holds when an admin removes a flow:
386
+ 5. What holds when a loop stops the new run, which is when `inner.stopped_on_loop` names a step (see "Read a run and its answers"), whatever type the step that started it is:
387
+ - Nothing is recorded in the parent run, not even `"ended"` for a step of a type that declares `chooses_flow_from_run`.
388
+ - No job is queued, on the page load that stops the new run or on any later page load or `advance` of it, so no `EasyFlow::InnerFlowError` is raised for it.
389
+ - The parent run stays at the step showing `Waiting for <name>.` on every page load, and `parent.waiting_on` is still the stopped run. Nothing in the engine moves it on.
390
+ - The new run's own `finished` is still called on its visitor's page load.
391
+ 6. What holds when an admin removes a flow:
386
392
  - Every run of the removed flow is deleted with it.
387
393
  - A run that one of those runs' Flow steps started is kept. Its `parent_run` becomes `nil` and its `parent_step` keeps the step id.
388
394
  - When such a kept run ends, nothing is recorded anywhere and no job is queued.
389
395
  - Removing a flow is refused while one of its runs is the run that a run of another flow is stopped at a Flow step waiting on, so a waiting run's `waiting_on` is never deleted this way.
390
396
  - A run of the removed flow that was started by a Flow step but is no longer waited on is deleted, so `run.inner_runs.find_by(parent_step: step_id)` returns `nil` for that step afterwards.
391
- 6. Find the runs:
397
+ 7. Find the runs:
392
398
  - `run.waiting_on` — the run started at the step `run` is stopped at, or `nil` when `run` is stopped at a step that started no run, or has reached its end.
393
399
  - `run.inner_runs.find_by(parent_step: step_id)` — the run started at a given step, or visit key such as `"sub@2"`, whether or not `run` is still stopped there.
394
400
  - `run.parent_run` — the run that started `run`.
395
- 7. Nothing takes the visitor from the parent run to the new run. Ask the developer how the visitor gets there, such as a link on the app's own page or a redirect from the app's controller, and where to show the new run, which is the `_run` route of the controller serving its host, such as `main_app.intake_run_path(run.waiting_on)`. Do not pick.
396
- 8. Nothing takes the visitor back to the parent run when the new run ends either. Ask the developer whether the visitor goes back, and if so override `finished(answers, run)` in the controller serving the new run's host to redirect when `run&.parent_run` is present, to the `_run` route of the controller serving the parent run's host. Check `run&.parent_run` and not `parent_step`, since a run whose parent flow was removed keeps its `parent_step` with no `parent_run`:
401
+ 8. Nothing takes the visitor from the parent run to the new run. Ask the developer how the visitor gets there, such as a link on the app's own page or a redirect from the app's controller, and where to show the new run, which is the `_run` route of the controller serving its host, such as `main_app.intake_run_path(run.waiting_on)`. Do not pick.
402
+ 9. Nothing takes the visitor back to the parent run when the new run ends either. Ask the developer whether the visitor goes back, and if so override `finished(answers, run)` in the controller serving the new run's host to redirect when `run&.parent_run` is present, to the `_run` route of the controller serving the parent run's host. Check `run&.parent_run` and not `parent_step`, since a run whose parent flow was removed keeps its `parent_step` with no `parent_run`:
397
403
 
398
404
  ```ruby
399
405
  def finished(answers, run)
@@ -403,11 +409,12 @@ Use this when a visitor's run reaches a Flow step and the app must take the visi
403
409
  end
404
410
  ```
405
411
 
406
- 9. The new run already belongs to the parent run's owner, so a run that should have an owner needs it set on the parent run before the parent reaches the Flow step, such as in `start_run(flow)`. Ask the developer whether the new run should belong to a different record, and if so set it where the app sends the visitor on, for example `run.waiting_on.update!(owner: ...)`.
407
- 10. Ask the developer what the visitor is shown when the parent run cannot start its new run, since `ActiveRecord::RecordNotFound`, `EasyFlow::InnerFlowError` or `ActiveRecord::RecordInvalid` is raised on the visitor's page load.
408
- 11. Ask the developer what each output of the named flow should lead to in the parent flow. Each different output on the named version's End steps is a connection leaving the Flow step on the canvas, which an admin connects, so no code is needed unless the app acts on the output itself. Only outputs written on built-in End steps are offered as connections, so a named flow that ends on a step of the app's own `ends_here` type hands over an output that matches no connection, and the parent run ends at the Flow step.
409
- 12. Ask the developer what should happen when a named flow ends with no output and its parent run is left waiting, such as admins writing an output on every End step of a flow another flow names, or the app watching for the failed job's `EasyFlow::InnerFlowError` and acting on the parent run. Do not pick. Publishing does not refuse a named flow whose End step has a blank output.
410
- 13. Publish a flow with a Flow step set to save each step, start a run with an owner, walk it to the Flow step, and check `run.waiting_on` is one run of the named flow with that run as its `parent_run` and the same `owner`, and that reloading the page starts no second one. Walk the new run to an End step, and check the parent run records that End step's output at the Flow step and moves on along the connection labelled with it. Walk another new run to an End step with a blank output, and check the parent run stays waiting and the queued job fails with `EasyFlow::InnerFlowError`. While a parent run waits on a new run, check that removing the named flow is refused. Remove the parent run's flow, and check the new run is kept with no `parent_run` and that finishing it neither raises nor queues a job.
412
+ 10. The new run already belongs to the parent run's owner, so a run that should have an owner needs it set on the parent run before the parent reaches the Flow step, such as in `start_run(flow)`. Ask the developer whether the new run should belong to a different record, and if so set it where the app sends the visitor on, for example `run.waiting_on.update!(owner: ...)`.
413
+ 11. Ask the developer what the visitor is shown when the parent run cannot start its new run, since `ActiveRecord::RecordNotFound`, `EasyFlow::InnerFlowError` or `ActiveRecord::RecordInvalid` is raised on the visitor's page load.
414
+ 12. Ask the developer what each output of the named flow should lead to in the parent flow. Each different output on the named version's End steps is a connection leaving the Flow step on the canvas, which an admin connects, so no code is needed unless the app acts on the output itself. Only outputs written on built-in End steps are offered as connections, so a named flow that ends on a step of the app's own `ends_here` type hands over an output that matches no connection, and the parent run ends at the Flow step.
415
+ 13. Ask the developer what should happen when a named flow ends with no output and its parent run is left waiting, such as admins writing an output on every End step of a flow another flow names, or the app watching for the failed job's `EasyFlow::InnerFlowError` and acting on the parent run. Do not pick. Publishing does not refuse a named flow whose End step has a blank output.
416
+ 14. Ask the developer what should happen when a loop stops a named flow's run and its parent run is left waiting. Do not pick. No job fails for it, so the app finds such a parent by its `waiting_on` run having a `stopped_on_loop`, such as `parent.waiting_on&.stopped_on_loop`.
417
+ 15. Publish a flow with a Flow step set to save each step, start a run with an owner, walk it to the Flow step, and check `run.waiting_on` is one run of the named flow with that run as its `parent_run` and the same `owner`, and that reloading the page starts no second one. Walk the new run to an End step, and check the parent run records that End step's output at the Flow step and moves on along the connection labelled with it. Walk another new run to an End step with a blank output, and check the parent run stays waiting and the queued job fails with `EasyFlow::InnerFlowError`. Walk another new run of a flow with a loop of Count steps only until the loop stops it, and check the parent run records nothing, stays waiting, and no job is queued. While a parent run waits on a new run, check that removing the named flow is refused. Remove the parent run's flow, and check the new run is kept with no `parent_run` and that finishing it neither raises nor queues a job.
411
418
 
412
419
  ### Decide which answers a step offers in a run
413
420
 
@@ -494,15 +501,15 @@ Use this when a visitor's run should stop until a set time has passed, such as a
494
501
  - `run.held_until` — the time the run is held until while stopped at a Wait step, or `nil`. See "Hold a run until a time".
495
502
  - `run.flow` — the flow it belongs to.
496
503
  - `run.owner` — the optional record the run belongs to, polymorphic, set by the app. `run.label` and `run.status` are free string columns for the app's own use.
497
- - `run.parent_run` and `run.parent_step` — the run whose Flow step started this one and that step's id, both `nil` for a run a visitor or the app started. Once this run ends with an output, `run.parent_run.recorded` holds that `output` under that step id. When it ends with none, nothing is recorded there. When an admin removed the flow the parent run belonged to, `parent_run` is `nil` and `parent_step` still holds the step id.
504
+ - `run.parent_run` and `run.parent_step` — the run whose Flow step started this one and that step's id, both `nil` for a run a visitor or the app started. Once this run ends with an output, `run.parent_run.recorded` holds that `output` under that step id. When it ends with none, nothing is recorded there. When a loop stops it, nothing is recorded there and no job is queued. When an admin removed the flow the parent run belonged to, `parent_run` is `nil` and `parent_step` still holds the step id.
498
505
  - `run.inner_runs` — the runs this run's Flow steps started.
499
506
  - `run.waiting_on` — the run started at the step this run is stopped at, or `nil` when no run was started there.
500
507
  - `run.pinned_definition` — the flow document of the version the run started on.
501
508
  - `run.next_step(answers)` and `run.walked(answers)` — the next step, and the answers on the path taken, for a set of answers against that pinned version, routed with the run's own `completed_at`.
502
509
  - `run.output` — the text the admin wrote into the output setting of the End step the run ended on, read from the run's pinned version. It is `nil` when the run has not reached an End step, or ended on one whose output was left blank. A flow may have several End steps with a different output on each, so the output says which way the flow ended. Ask the developer what the app does with each output, and what it does when there is none.
503
510
  - `run.ended_at_end?` — `true` when the run is not stopped at a step that awaits input, computes a value or waits, and the last step it reached is of a type that declares `ends_here`, such as the built-in End step, whether or not that step has an output. It is `false` while the run is still going, including while it waits at a Flow step, when a loop stopped it, and when it ended at a step that is not an end, such as a step with no connection leaving it or a `route` value that matches no connection's label. Use it to tell a run that ended at an End step with a blank output from one that stopped anywhere else, since `run.output` is `nil` for both.
504
- - `run.stopped_on_loop` — the id of the step a loop came back to when it stopped the run, as a string, the plain step id and never a visit key such as `"tally@2"`, or `nil` when no loop stopped it. A loop stops the run when it comes back to a step already visited with no step that awaits input answered since that step's last visit, such as a loop of Count steps only. The run ends there, and `run.ended_at_end?` is `false`. Ask the developer what the app does with a run a loop stopped, such as showing an admin the step named. Do not pick.
505
- - `run.advance` — moves the run past every waiting step whose `waits_until` block now returns a truthy value, and past every step that computes a value, and records each result on the run. It stops at the next step that asks the visitor for input, the next waiting step that is not ready, or the end. It does not call `finished`; that is called the next time the visitor loads the run's page. When it stops at a Flow step it starts that step's run, and when it reaches the end of a run a Flow step started it hands the output to the parent run; see "Follow a run into the flow a Flow step started".
511
+ - `run.stopped_on_loop` — the id of the step a loop came back to when it stopped the run, as a string, the plain step id and never a visit key such as `"tally@2"`, or `nil` when no loop stopped it. A loop stops the run when it comes back to a step already visited with no step that awaits input answered since that step's last visit, such as a loop of Count steps only. The run ends there, and `run.ended_at_end?` is `false`. When a Flow step started the run, nothing is handed to its parent run, which stays waiting at that step; see step 5 of "Follow a run into the flow a Flow step started". Ask the developer what the app does with a run a loop stopped, such as showing an admin the step named. Do not pick.
512
+ - `run.advance` — moves the run past every waiting step whose `waits_until` block now returns a truthy value, and past every step that computes a value, and records each result on the run. It stops at the next step that asks the visitor for input, the next waiting step that is not ready, or the end. It does not call `finished`; that is called the next time the visitor loads the run's page. When it stops at a Flow step it starts that step's run, and when it reaches the end of a run a Flow step started it hands the output to the parent run, unless a loop stopped the run; see "Follow a run into the flow a Flow step started".
506
513
  3. To show answers with their question text and answer labels, build a runner from the run's pinned document:
507
514
 
508
515
  ```ruby
@@ -536,7 +543,7 @@ Use this when a visitor's run should stop until a set time has passed, such as a
536
543
  - A `chooses_flow` block is given only the step, finds the flow by id with no host or owner scope, and is called on every canvas draw, name shown, save and publish, so it limits the flows it names itself and changes nothing.
537
544
  - A step of a `chooses_flow` type with no `names_by` is named by the chosen flow's title and version number.
538
545
  - A `chooses_flow_from_run` block is called only when a stored run stops at the step, finds the flow by id with no host or owner scope, and is never checked on save or publish, so the block limits the flows it names itself.
539
- - A run started by a `chooses_flow_from_run` step that ends with no output records `"ended"` at that step, and the parent run moves on.
546
+ - A run started by a `chooses_flow_from_run` step that ends with no output records `"ended"` at that step, and the parent run moves on, unless a loop stopped it.
540
547
  - A host's `allowed_answers` lambda is given only the step and the answers recorded so far, and is called many times per page load, so it reads only those and changes nothing.
541
548
  - A step the host allows one answer is recorded without being shown, and one it allows none is recorded as `""` and skipped, whatever the step's type.
542
549
  - A runner the app builds without `host:` ignores the host's `allowed_answers`.
@@ -569,6 +576,7 @@ Use this when a visitor's run should stop until a set time has passed, such as a
569
576
  - A run started by a Flow step takes the owner its parent run had when it was started, and nothing sends the visitor to it or back from it.
570
577
  - A run that reaches a Flow step waits there until the run it started ends with an output, then records that output and follows the connection labelled with it.
571
578
  - A run started by a Flow step that ends with no output leaves its parent run waiting at the Flow step, and each job queued to move the parent on fails with `EasyFlow::InnerFlowError`.
579
+ - A run started by a Flow step or any `starts_a_flow` step that a loop stopped hands nothing to its parent run and queues no job, so the parent run waits at that step with nothing failing to report it.
572
580
  - A Flow step whose named version was retired or withdrawn after publishing raises `EasyFlow::InnerFlowError` naming the step when a run stops there.
573
581
  - A parent run is moved on by an Active Job job, so the app's queue adapter must run jobs for it to move on without its visitor reloading.
574
582
  - Only a stored run starts a run at a Flow step.
@@ -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, flows that loop back to ask a step again, a loop that stops a run when nothing new was answered and the step it came back to, whether a run ended at an End step, hosts and the step types each offers its admins, runs and the published version each starts on, each visit a run records with its value and the time the step was completed, and the output a flow gives when it ends, the built-in step types including questions and checklists that can require an answer and explain each answer behind an info button, file upload steps that hand a visitor's file to the app's file store and read it back by its name, and branching on an answer, including one named output of a step that recorded several, on comparing a number with an amount, or on comparing two earlier answers, branching on a list of such comparisons that must all hold or of which any one must hold, branching on the hour, weekday or minute a step was completed, Wait steps that hold a run until a number of minutes or a time of day after an earlier step was completed, or until a date, and are named after what they wait for, the Check again button a visitor sees at a waiting step in a flow that keeps nothing, Count steps that count how often an earlier step was answered so a loop can give up after a number of tries, Flow steps that name another flow, open its canvas when their card is clicked with a button back to the flow it was opened from, start a run of it for the same owner when a stored run reaches them, are flagged when the flow or version they name cannot run or leads back to the flow they sit in, let the waiting run name that inner run, move that run on along the output it ends with, and fail with an error naming the step when its version was taken out of service or its inner run ended with no output, removing a flow and why it is refused while a waiting run depends on it, step types the host app registers, including ones whose outputs are named by the entries an admin lists in one of their settings, ones that start another flow and work out which flow and version to run from their own settings and are named after that flow, or choose it from the run they are in, the answers a host allows a step in a run and the steps it fills in or passes over, the checks they make on an answer, what a step shows a visitor and how that can depend on the visitor's run, and steps that hold a run until something outside the flow has happened, and the settings an admin fills in, including picks whose options come from the app's data and settings kept on one of the app's own records.
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, flows that loop back to ask a step again, a loop that stops a run when nothing new was answered and the step it came back to, whether a run ended at an End step, hosts and the step types each offers its admins, runs and the published version each starts on, each visit a run records with its value and the time the step was completed, and the output a flow gives when it ends, the built-in step types including questions and checklists that can require an answer and explain each answer behind an info button, file upload steps that hand a visitor's file to the app's file store and read it back by its name, and branching on an answer, including one named output of a step that recorded several, on comparing a number with an amount, or on comparing two earlier answers, branching on a list of such comparisons that must all hold or of which any one must hold, branching on the hour, weekday or minute a step was completed, Wait steps that hold a run until a number of minutes or a time of day after an earlier step was completed, or until a date, and are named after what they wait for, the Check again button a visitor sees at a waiting step in a flow that keeps nothing, Count steps that count how often an earlier step was answered so a loop can give up after a number of tries, Flow steps that name another flow, open its canvas when their card is clicked with a button back to the flow it was opened from, start a run of it for the same owner when a stored run reaches them, are flagged when the flow or version they name cannot run or leads back to the flow they sit in, let the waiting run name that inner run, move that run on along the output it ends with, leave it waiting when the inner run is stopped by a loop, and fail with an error naming the step when its version was taken out of service or its inner run ended with no output, removing a flow and why it is refused while a waiting run depends on it, step types the host app registers, including ones whose outputs are named by the entries an admin lists in one of their settings, ones that start another flow and work out which flow and version to run from their own settings and are named after that flow, or choose it from the run they are in, the answers a host allows a step in a run and the steps it fills in or passes over, the checks they make on an answer, what a step shows a visitor and how that can depend on the visitor's run, and steps that hold a run until something outside the flow has happened, and the settings an admin fills in, including picks whose options come from the app's data and settings kept on one of the app's own records.
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
  ---
@@ -82,7 +82,7 @@ easy_flow declares no commands of its own for this local. Its surface is split b
82
82
  - **Flow-starting step type** — a step type of the app's own that starts another flow the way the Flow step does. By default it runs the flow and version named in its settings called flow and version. It may instead carry a rule that works out the flow and version from its other settings, and that choice is then used everywhere a Flow step's choice is: starting the inner run, the unrunnable and circular checks, and the canvas link to that flow. When the step type gives the step no name of its own, the step is named after the flow and version that rule works out, the same way a Flow step is, such as "Onboarding, version 2", on its canvas card and in the "Waiting for" line a visitor sees. Everything said below about a Flow step's inner run and handing back applies to it too, except where a run-chosen flow says otherwise.
83
83
  - **Run-chosen flow** — a flow-starting step type of the app's own that chooses the flow and version from the run it is in rather than from its settings, so two runs of one flow can start two different inner flows from the same step. Where there is no run, such as on the canvas, it has no chosen flow. Its steps are left out of the unrunnable and circular checks, so a flow holding one can be published with no flow in its settings. A run that reaches it and has no flow chosen fails with an error naming the step. When its inner run ends with no output, the step records `ended` and its run moves on.
84
84
  - **Inner run** — the run a Flow step starts. It records which run started it and at which step, and that run holds at most one inner run for each Flow step, however often it is moved on. It belongs to the same owner as the run that started it. When the picked version has been retired or withdrawn, no inner run is started and the run that reached the Flow step fails with an error naming that step. While the run that started it is stopped at the Flow step, that run can name the inner run it is waiting on, and it names none when it is stopped at any other step or has finished. Its steps that act on their own run as soon as it starts, and it stops at its first step that asks for input or waits.
85
- - **Handing back** — what happens when an inner run ends. Its flow output is recorded in the run that started it, as that run's answer at the Flow step, and a background job then moves that run on along the connection labelled with the output. An inner run that ended with no output records nothing in the run that started it, and the background job then fails with an error naming the Flow step, so that run does not move on. An output is handed back only once, so an inner run moved on again after it ended changes nothing. Because the move happens in a background job, the app must run its jobs for a run to go past a Flow step.
85
+ - **Handing back** — what happens when an inner run ends. Its flow output is recorded in the run that started it, as that run's answer at the Flow step, and a background job then moves that run on along the connection labelled with the output. An inner run that ended with no output records nothing in the run that started it, and the background job then fails with an error naming the Flow step, so that run does not move on. An inner run that a loop stopped hands nothing back and starts no background job, so the run that started it stays stopped at the Flow step and still names that inner run as the one it is waiting on. An output is handed back only once, so an inner run moved on again after it ended changes nothing. Because the move happens in a background job, the app must run its jobs for a run to go past a Flow step.
86
86
  - **Waiting step** — a step whose type carries a rule saying whether what it waits for has happened, such as a payment clearing or a document being signed. A run that reaches it stops there, and the visitor sees "Waiting for" followed by the step's name, with no form to submit. Once the rule says it has happened, the run moves past the step the next time the visitor's page is loaded or the app moves the run on, and the step is recorded as `true`.
87
87
  - **Check again** — a button a visitor sees under the "Waiting for" line in a flow that carries its answers in the page. It loads the step page again with the answers and their completion times, so the run moves past a waiting step whose rule now says it has happened, such as a Wait step whose time has come. A stored run shows no such button, since loading its page again does the same.
88
88
  - **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, and its answers are not checked.
@@ -96,7 +96,7 @@ easy_flow declares no commands of its own for this local. Its surface is split b
96
96
  - **Answers** — the recorded values of a run, keyed by visit. The next step is always worked out from these values, their completion times and the connections in the pinned version.
97
97
  - **Loop** — a connection that leads back to a step the run has already passed, so that step is visited again. Branching steps read the most recent answer to a step, so a loop ends when an answer sends the run down a different connection. Reading a finished run again follows the same connections it took at the time, since each branching step reads the answers as they stood at that visit.
98
98
  - **Visit** — one time a run reaches a step. The first visit is keyed by the step id alone, and each later visit is keyed by the step id, an `@`, and the visit number, such as `size@2`. Every visit's value and completion time are kept, and a finished run lists each one.
99
- - **Stopped loop** — a run that comes back to a step with no new answer given since its last visit there ends at that point rather than cycling forever. Only answers the visitor gives count, so a loop made only of steps that act on their own stops the first time it comes round. A stored run stopped this way names the step the loop came back to, and does not count as having ended at an End step.
99
+ - **Stopped loop** — a run that comes back to a step with no new answer given since its last visit there ends at that point rather than cycling forever. Only answers the visitor gives count, so a loop made only of steps that act on their own stops the first time it comes round. A stored run stopped this way names the step the loop came back to, and does not count as having ended at an End step. An inner run stopped this way leaves the run that started it at its Flow step, as described under handing back.
100
100
  - **Ended at an End step** — whether a stored run's path finished on an End step, or on a step of the app's own type that ends a flow. It does not while the run is still going or held at a step, when a loop stopped it, or when it stopped at a step with no connection to follow.
101
101
  - **Reserved `@`** — a step id may not contain `@`, since that mark numbers later visits. A flow holding such a step id is reported as invalid.
102
102
  - **Refused answer** — an answer the step's answer check turned down. Nothing is recorded for that step, and the visitor is shown the same step again with the check's message. This works the same whether the flow keeps a stored run or carries its answers in the page.
@@ -117,6 +117,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
117
117
  - When a stored run reaches a Flow step, the engine starts a run of the chosen flow and records the run it was started from. That record needs the migration that adds a parent run to the runs table, so an app upgrading from a version without it runs `bin/rails easy_flow:install:migrations` and `bin/rails db:migrate` before publishing a flow with a Flow step.
118
118
  - After publishing a flow with a Flow step, check that when a visitor finishes the chosen flow, the run that holds the Flow step moves on along the connection named after the output that flow ended with. If it stays at the Flow step, check the queue adapter from step 12.
119
119
  - When a chosen flow ends at an End step with no output filled in, the engine records nothing at the Flow step, and the job queued on `default` fails with `EasyFlow::InnerFlowError` naming the Flow step. The run that holds the Flow step stays at it. Check that the queue adapter from step 12 keeps or reports failed jobs, and that every End step of a flow chosen on a Flow step has an output.
120
+ - When a loop stops a run started by a Flow step, or by a step type of the app's own that starts a flow, the engine records nothing at the step that started it and queues no job. A loop stops a run when it comes back to a step with no answer given since the last visit to that step. The run that holds the starting step stays at it and no error is raised. This holds for a step type of the app's own that chooses the flow from the run as well, so it records no `ended` answer either. Check that every loop in a flow chosen on a Flow step passes a step that waits for the visitor's answer.
120
121
  - When a run reaches a Flow step whose chosen version was retired or withdrawn after the flow was published, the engine raises `EasyFlow::InnerFlowError` naming the Flow step and starts no run. The engine does not turn this error into a refusal, so the visitor gets the app's error page. Check that the app's error reporting captures it.
121
122
  - After install, check that removing a flow from `<mount path>/manage/flows` shows "Flow removed." and takes the flow off the list. Removing a flow deletes its versions and its runs, and needs no setting in the initializer.
122
123
  - After publishing a flow with a Flow step, check that while a run of it is stopped at that Flow step, removing the chosen flow is refused and the flow list shows "This flow cannot be removed while" followed by the waiting flow's title, or its slug when it has no title, and "waits on one of its runs". If no message is shown, check that the admin layout shows `flash[:alert]`.
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.19.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tylercschneider