petri_flow 0.1.6 → 0.1.7

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: 5fab8df9f2e3aab0e596f470cab3b32c81bd395d9693a761c64b671b78c01a7e
4
- data.tar.gz: befe8793cab6a2b5f07ab2cd7f80621832949354557dbdb7d54ea07ee4cdb8e8
3
+ metadata.gz: b75f2ac3288f2b169d4364a8aaa11586497d710477ecabe92adb6af2ffbf7376
4
+ data.tar.gz: 3a12e23472cc059ba4437ee1535d216b4df290f64d1de05c54a8395a648c5246
5
5
  SHA512:
6
- metadata.gz: 9e959b6a9e7283e0546fba60f1284c43f633850f175ae41ec57f68dd7bf794e9f3130c1ffdb5a51630c1a7a588b30615b7e70a4029436c2f4cc27b315c81eb4a
7
- data.tar.gz: 742a8b6b01db351fd78ec40df6b3bcb96415f46a1c24cc6c8429a2261101764028ed146bd9b2d2798cb8a5b8875839ac53759476c0ae29aadd1e03f2f2a75f9c
6
+ metadata.gz: 6aad07e5b69eb1ed0046afaa59f9679a3f77b259fa7410533eb2939883b43da7adf7518fe4b4d17e1d3f3f3b40feca8d12c954d9c837ca9c052bf1af84385942
7
+ data.tar.gz: e278b0c46d95a0b7744ef457ebac2d8f8f56d5ac943ff009264086490b762378cfb37ea3e7c5b64362d7fe09d674374f48bb0eb4008f90d7aa732343cd1cd4f0
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Petri Flow ![Ruby Gem](https://github.com/hooopo/petri_flow/workflows/Ruby%20Gem/badge.svg?event=push)
1
+ # Petri Flow ![Ruby Gem](https://github.com/hooopo/petri_flow/workflows/Ruby%20Gem/badge.svg?event=push) ![Testing](https://github.com/hooopo/petri_flow/workflows/Testing/badge.svg?event=push)
2
2
 
3
3
  Workflow engine for Rails.
4
4
 
@@ -67,6 +67,7 @@ Migration:
67
67
  bundle exec rake wf:install:migrations
68
68
  bundle exec rails db:create
69
69
  bundle exec rails db:migrate
70
+ bundle exec rails db:seed
70
71
  ```
71
72
  ## Usage
72
73
 
@@ -116,7 +117,9 @@ visit:
116
117
  http://localhost:3000/wf
117
118
  ```
118
119
 
119
- Demo App: https://github.com/hooopo/petri_flow_demo
120
+ ## Testing
121
+
122
+ * RAILS_ENV=test rake app:db:migrate && RAILS_ENV=test rake app:db:test:prepare && bundle exec rake test
120
123
 
121
124
  ## Contributing
122
125
  Contribution directions go here.
@@ -40,7 +40,7 @@ module Wf
40
40
 
41
41
  def update
42
42
  @arc = Wf::Arc.find(params[:arc_id])
43
- gp = guard_params.merge(fieldable: GlobalID::Locator.locate(guard_params[:fieldable])) if guard_params[:fieldable].present?
43
+ gp = guard_params.merge(fieldable: GlobalID::Locator.locate(guard_params[:fieldable]))
44
44
  @guard = @arc.guards.find(params[:id])
45
45
  if @guard.update(gp)
46
46
  redirect_to workflow_arc_path(@arc.workflow, @arc), notice: "guard was successfully created."
@@ -10,6 +10,7 @@ module Wf::CaseCommand
10
10
 
11
11
  def call
12
12
  raise("The workitem is not in state #{workitem.state}") unless workitem.started?
13
+
13
14
  Wf::ApplicationRecord.transaction do
14
15
  workitem.update!(state: :canceled, canceled_at: Time.zone.now)
15
16
  ReleaseToken.call(workitem)
@@ -28,6 +28,10 @@ module Wf
28
28
  field_values.includes(:field).map { |x| [x.field_id.to_i, { field_id: x.id.to_i, field_name: x.field.name, value: x.value_after_cast }] }.to_h
29
29
  end
30
30
 
31
+ def for_mini_racer
32
+ field_values.includes(:field).map { |x| [x.field.name, x.value_after_cast] }.to_h
33
+ end
34
+
31
35
  def update_payload!
32
36
  update(payload: json)
33
37
  end
@@ -27,6 +27,8 @@ module Wf
27
27
  self.workflow = arc.workflow
28
28
  end
29
29
 
30
+ validate :validate_exp_and_fieldable
31
+
30
32
  OP = %w[
31
33
  =
32
34
  >
@@ -38,36 +40,76 @@ module Wf
38
40
 
39
41
  def value_after_cast
40
42
  field = fieldable
41
- if fieldable
42
- fieldable.cast(value)
43
+ fieldable&.cast(value)
44
+ end
45
+
46
+ def pass?(entry, workitem)
47
+ if exp
48
+ check_exp(entry, workitem)
43
49
  else
44
- # TODO
50
+ check_fieldable(entry)
45
51
  end
46
52
  end
47
53
 
48
- def pass?(entry)
54
+ def check_exp(entry, workitem)
55
+ form_hash = if entry
56
+ entry.for_mini_racer
57
+ else
58
+ {}
59
+ end
60
+
61
+ target_hash = workitem&.case&.targetable&.attributes || {}
62
+ user_hash = workitem&.holding_user&.attributes || {}
63
+
64
+ # 1000ms, 200mb
65
+ context = MiniRacer::Context.new(timeout: 1000, max_memory: 200_000_000)
66
+ context.eval("let form = #{form_hash.to_json};")
67
+ context.eval("let user = #{user_hash.to_json};")
68
+ context.eval("let target = #{target_hash.to_json};")
69
+ exp_value = context.eval(exp)
70
+ yes_or_no?(exp_value, value)
71
+ end
72
+
73
+ def check_fieldable(entry)
49
74
  fv = entry.field_values.where(field_id: fieldable_id).first
50
75
  return unless fv
51
76
 
77
+ yes_or_no?(fv.value_after_cast, value_after_cast)
78
+ end
79
+
80
+ def yes_or_no?(input_value, setting_value)
52
81
  if op == "="
53
- fv.value_after_cast == value_after_cast
82
+ input_value == setting_value
54
83
  elsif op == ">"
55
- fv.value_after_cast > value_after_cast
84
+ input_value > setting_value
56
85
  elsif op == "<"
57
- fv.value_after_cast < value_after_cast
86
+ input_value < setting_value
58
87
  elsif op == ">="
59
- fv.value_after_cast >= value_after_cast
88
+ input_value >= setting_value
60
89
  elsif op == "<="
61
- fv.value_after_cast <= value_after_cast
90
+ input_value <= setting_value
62
91
  elsif op == "is_empty"
63
- fv.value_after_cast.blank?
92
+ input_value.blank?
64
93
  else
65
94
  false
66
95
  end
67
96
  end
68
97
 
69
98
  def inspect
70
- %(#{fieldable&.form&.name}.#{fieldable&.name} #{op} #{value})
99
+ if exp
100
+ %(eval(exp) #{op} #{value})
101
+ else
102
+ %(#{fieldable&.form&.name}.#{fieldable&.name} #{op} #{value})
103
+ end
104
+ end
105
+
106
+ def validate_exp_and_fieldable
107
+ if fieldable && exp.present?
108
+ errors.add(:exp, "Exp and Fieldable can not be set at the same time.")
109
+ return
110
+ end
111
+
112
+ errors.add(:exp, "Must set one of Exp and Fieldable.") unless fieldable || exp.present?
71
113
  end
72
114
  end
73
115
  end
@@ -44,13 +44,12 @@ module Wf
44
44
  "Workitem -> #{id}"
45
45
  end
46
46
 
47
- # TODO: guards exp && target guards
48
47
  def pass_guard?(arc, has_passed = false)
49
48
  if arc.guards_count == 0
50
49
  !has_passed
51
50
  else
52
51
  entry = entries.where(user: holding_user).first
53
- arc.guards.all? { |guard| guard.pass?(entry) }
52
+ arc.guards.all? { |guard| guard.pass?(entry, self) }
54
53
  end
55
54
  end
56
55
 
@@ -58,7 +58,11 @@
58
58
  <td><%= guard.fieldable&.form&.name %>/<%= guard.fieldable&.name %></td>
59
59
  <td><%= guard.op %></td>
60
60
  <td><%= guard.value %></td>
61
- <td><%= guard.exp %></td>
61
+ <td>
62
+ <pre>
63
+ <%= guard.exp %>
64
+ </pre>
65
+ </td>
62
66
  <td><%= link_to 'Edit Guard', edit_arc_guard_path(@arc, guard), class: 'btn btn-sm btn-info' %></td>
63
67
  <td><%= link_to 'Delete Guard', [@arc, guard], remote: true, method: :delete, data: {confirm: 'confirm?'}, class: 'btn btn-sm btn-info' %></td>
64
68
  </tr>
@@ -18,7 +18,12 @@
18
18
 
19
19
  <div class="form-group">
20
20
  <%= f.label :fieldable, class: "label" %>
21
- <%= f.select :fieldable, options_for_select(@arc.transition.form&.fields&.map {|x| [x.name, x.to_global_id]} || [], selected: f.object&.fieldable&.to_global_id), {}, class: "form-control custom-select", placeholder: "fieldable" %>
21
+ <%= f.select :fieldable, options_for_select(@arc.transition.form&.fields&.map {|x| [x.name, x.to_global_id]} || [], selected: f.object&.fieldable&.to_global_id), {include_blank: "select a field"}, class: "form-control custom-select", placeholder: "fieldable" %>
22
+ </div>
23
+
24
+ <div class="form-group">
25
+ <%= f.label :exp, class: "label" %> <small>JavaScript with build-in variable <span class="badge badge-danger">user</span>, <span class="badge badge-danger">form</span>, <span class="badge badge-danger">target</span>.</small>
26
+ <%= f.text_area :exp, class: "form-control", placeholder: "Exp", rows: 8 %>
22
27
  </div>
23
28
 
24
29
  <div class="form-group">
@@ -32,11 +37,6 @@
32
37
  <%= f.text_field :value, class: "form-control", placeholder: "Value" %>
33
38
  </div>
34
39
 
35
- <div class="form-group">
36
- <%= f.label :exp, class: "label" %>
37
- <%= f.text_field :exp, class: "form-control", placeholder: "Exp" %>
38
- </div>
39
-
40
40
  <div class="form-group">
41
41
  <%= f.submit class: "btn btn-primary", data: {disable_with: 'Waiting...'} %>
42
42
  </div>
data/lib/wf/engine.rb CHANGED
@@ -29,3 +29,4 @@ require "rgl/traversal"
29
29
  require "rgl/path"
30
30
  require "active_record/connection_adapters/postgresql_adapter.rb"
31
31
  require "select2-rails"
32
+ require "mini_racer"
data/lib/wf/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wf
4
- VERSION = "0.1.6"
4
+ VERSION = "0.1.7"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: petri_flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hooopo Wang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-15 00:00:00.000000000 Z
11
+ date: 2020-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bootstrap
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mini_racer
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: pg
85
99
  requirement: !ruby/object:Gem::Requirement