petri_flow 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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