Skip to content

Commit

Permalink
Ref #22 -- Simplify tutorial by joining state and behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
codingjoe committed Nov 4, 2020
1 parent 8851196 commit 25fd79a
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 61 deletions.
10 changes: 5 additions & 5 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ may look like:
from joeflow import tasks
class Shipment(Workflow):
class ShippingWorkflow(Workflow):
# model fields to store the state
email = models.EmailField(blank=True)
shipping_address = models.TextField()
tracking_code = models.TextField()
class ShippingWorkflow(Shipment):
# tasks (nodes)
checkout = tasks.StartView(fields=["shipping_address", "email"])
ship = tasks.UpdateView(fields=["tracking_code"])
Expand All @@ -66,6 +68,7 @@ may look like:
def end(self):
pass
# edges
edges = [
(checkout, ship),
(ship, has_email),
Expand All @@ -74,9 +77,6 @@ may look like:
(send_tracking_code, end),
]
class Meta:
proxy = True
Design Principles
=================

Expand Down
25 changes: 14 additions & 11 deletions docs/tutorial/workflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,32 @@ store a user. Like so:
from joeflow.models import Workflow
class WelcomeWorkflowState(Workflow):
class WelcomeWorkflow(Workflow):
# state
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True, null=True,
)
We keep the model abstract. The abstract model will make it easier to separate
state from behavior and therefore easier to read for your fellow developers.

Next we add the behavior:

.. code-block:: python
from django.conf import settings
from joeflow import tasks
from joeflow.models import Workflow
from . import models
class WelcomeWorkflow(Workflow):
# state
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True, null=True,
)
class WelcomeWorkflow(models.WelcomeWorkflowState):
# behavior
start = tasks.StartView(fields=["user"])
def has_user(self):
Expand All @@ -76,8 +81,6 @@ Next we add the behavior:
(send_welcome_email, end),
]
class Meta:
proxy = True
We have the tasks ``start``, ``has_user`` ``send_welcome_email`` and ``end``
on the top and define all the edges on the bottom. Edges are defined by a
Expand All @@ -101,11 +104,11 @@ to your ``urls.py``:
from django.urls import path, include
from . import workflows
from . import models
urlpatterns = [
#
path('welcome/', include(workflows.WelcomeWorkflow.urls())),
path('welcome/', include(models.WelcomeWorkflow.urls())),
]
This will add URLs for all human tasks as well as a detail view and manual
Expand Down
12 changes: 6 additions & 6 deletions tests/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.test import SimpleTestCase, TestCase
from django.urls import reverse

from .testapp import workflows
from .testapp import models


class WelcomeWorkflowMachineTest(SimpleTestCase):
Expand All @@ -14,11 +14,11 @@ def test_has_user__with_user(self):
last_name="Parker",
username="spidy",
)
workflow = workflows.WelcomeWorkflow(user=user)
workflow = models.WelcomeWorkflow(user=user)
self.assertEqual(workflow.has_user(), [workflow.send_welcome_email])

def test_has_user__without_user(self):
workflow = workflows.WelcomeWorkflow()
workflow = models.WelcomeWorkflow()
self.assertEqual(workflow.has_user(), [workflow.end])

def test_send_welcome_email(self):
Expand All @@ -28,7 +28,7 @@ def test_send_welcome_email(self):
last_name="Parker",
username="spidy",
)
workflow = workflows.WelcomeWorkflow(user=user)
workflow = models.WelcomeWorkflow(user=user)

workflow.send_welcome_email()

Expand All @@ -55,13 +55,13 @@ def test_start__post_with_user(self):

response = self.client.post(self.start_url, data=dict(user=user.pk))
self.assertEqual(response.status_code, 302)
workflow = workflows.WelcomeWorkflow.objects.get()
workflow = models.WelcomeWorkflow.objects.get()
self.assertTrue(workflow.user)
self.assertTrue(workflow.task_set.succeeded().filter(name="start").exists())

def test_start__post_without_user(self):
response = self.client.post(self.start_url)
self.assertEqual(response.status_code, 302)
workflow = workflows.WelcomeWorkflow.objects.get()
workflow = models.WelcomeWorkflow.objects.get()
self.assertFalse(workflow.user)
self.assertTrue(workflow.task_set.succeeded().filter(name="start").exists())
8 changes: 1 addition & 7 deletions tests/testapp/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class Migration(migrations.Migration):
bases=("joeflow.workflow",),
),
migrations.CreateModel(
name="WelcomeWorkflowState",
name="WelcomeWorkflow",
fields=[
(
"workflow_ptr",
Expand Down Expand Up @@ -231,10 +231,4 @@ class Migration(migrations.Migration):
options={"proxy": True, "indexes": [], "constraints": []},
bases=("testapp.waitworkflowstate",),
),
migrations.CreateModel(
name="WelcomeWorkflow",
fields=[],
options={"proxy": True, "indexes": [], "constraints": []},
bases=("testapp.welcomeworkflowstate",),
),
]
29 changes: 28 additions & 1 deletion tests/testapp/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.conf import settings
from django.db import models

from joeflow import tasks
from joeflow.models import Workflow


Expand All @@ -10,14 +11,40 @@ class Shipment(Workflow):
tracking_code = models.TextField()


class WelcomeWorkflowState(Workflow):
class WelcomeWorkflow(Workflow):
# state
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True,
)

# behavior
start = tasks.StartView(fields=["user"])

def has_user(self):
if self.user:
return [self.send_welcome_email]
else:
return [self.end]

def send_welcome_email(self):
self.user.email_user(
subject="Welcome",
message="Hello %s!" % self.user.get_short_name(),
)

def end(self):
pass

edges = [
(start, has_user),
(has_user, end),
(has_user, send_welcome_email),
(send_welcome_email, end),
]


class SimpleWorkflowState(Workflow):
pass
Expand Down
4 changes: 2 additions & 2 deletions tests/testapp/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from django.contrib import admin
from django.urls import include, path

from . import workflows
from . import models, workflows

urlpatterns = [
path("admin/", admin.site.urls),
Expand All @@ -26,5 +26,5 @@
path("gateway/", include(workflows.GatewayWorkflow.urls())),
path("splitjoin/", include(workflows.SplitJoinWorkflow.urls())),
path("loop/", include(workflows.LoopWorkflow.urls())),
path("welcome/", include(workflows.WelcomeWorkflow.urls())),
path("welcome/", include(models.WelcomeWorkflow.urls())),
]
29 changes: 0 additions & 29 deletions tests/testapp/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,35 +40,6 @@ class Meta:
proxy = True


class WelcomeWorkflow(models.WelcomeWorkflowState):
start = tasks.StartView(fields=["user"])

def has_user(self):
if self.user:
return [self.send_welcome_email]
else:
return [self.end]

def send_welcome_email(self):
self.user.email_user(
subject="Welcome",
message="Hello %s!" % self.user.get_short_name(),
)

def end(self):
pass

edges = [
(start, has_user),
(has_user, end),
(has_user, send_welcome_email),
(send_welcome_email, end),
]

class Meta:
proxy = True


class SimpleWorkflow(models.SimpleWorkflowState):
start_view = tasks.StartView(fields="__all__", path="custom/postfix/")
start_method = tasks.Start()
Expand Down

0 comments on commit 25fd79a

Please sign in to comment.