aristotle 0.0.4 → 0.1.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 +4 -4
- data/lib/aristotle.rb +2 -0
- data/lib/aristotle/command.rb +39 -0
- data/lib/aristotle/logic.rb +32 -96
- data/lib/aristotle/presenter.rb +22 -0
- data/lib/aristotle/utility.rb +51 -4
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 08566772bb5f4c2458e5eff1058c23f87601805c
|
4
|
+
data.tar.gz: 804ce18d078fc5ab280fce17d39dec1994f33dea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4199a7fd2511951eaf4ba159e6b8bceb86293e1d1d81676858064e3209d7eb492b2b7d99651f0905e0956edcf65996c77695c2d74d134c5e708681838a41492
|
7
|
+
data.tar.gz: c2c2413a36d7d18b92b6aa9e659b55951e3c18a9b84fa8d268a505811e5b1bd5b304d2d075be9a4d3c5ccbc5937997b62a83999d161c328f4b72e7b707a90bc3
|
data/lib/aristotle.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Aristotle
|
2
|
+
class Command
|
3
|
+
attr_reader :action, :condition
|
4
|
+
|
5
|
+
def initialize(line, conditions, actions)
|
6
|
+
# TODO: make this properly work with regexps
|
7
|
+
@action, @condition = line.split(' if ', 2).map(&:strip)
|
8
|
+
|
9
|
+
raise 'Badly formatted line' if @action == '' || @condition == ''
|
10
|
+
|
11
|
+
@condition_proc = conditions[Regexp.new(@condition)]
|
12
|
+
@action_proc = actions[Regexp.new(@action)]
|
13
|
+
end
|
14
|
+
|
15
|
+
def do_action_with(object)
|
16
|
+
if @action_proc
|
17
|
+
@action_proc.call(object)
|
18
|
+
else
|
19
|
+
raise "Action not found: #{@action}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def condition_passes_with?(object)
|
24
|
+
if @condition_proc
|
25
|
+
@condition_proc.call(object)
|
26
|
+
else
|
27
|
+
raise "Condition not found: #{@condition}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_action?
|
32
|
+
!@action_proc.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def has_condition?
|
36
|
+
!@condition_proc.nil?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/aristotle/logic.rb
CHANGED
@@ -4,14 +4,31 @@ module Aristotle
|
|
4
4
|
@object = object
|
5
5
|
end
|
6
6
|
|
7
|
+
def process(logic_method)
|
8
|
+
self.class.commands(logic_method).each do |command|
|
9
|
+
next unless command.condition_passes_with?(@object)
|
10
|
+
|
11
|
+
return command.do_action_with(@object)
|
12
|
+
end
|
13
|
+
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.commands(logic_method = nil)
|
18
|
+
load_commands
|
19
|
+
logic_method.nil? ? @@commands : (@@commands[logic_method] || [])
|
20
|
+
end
|
21
|
+
|
22
|
+
# called when class is loaded
|
7
23
|
def self.condition(expression, &block)
|
8
24
|
@@conditions ||= {}
|
9
|
-
@@conditions[expression
|
25
|
+
@@conditions[expression] = block
|
10
26
|
end
|
11
27
|
|
28
|
+
# called when class is loaded
|
12
29
|
def self.action(expression, &block)
|
13
30
|
@@actions ||= {}
|
14
|
-
@@actions[expression
|
31
|
+
@@actions[expression] = block
|
15
32
|
end
|
16
33
|
|
17
34
|
def self.load_commands
|
@@ -19,115 +36,34 @@ module Aristotle
|
|
19
36
|
|
20
37
|
return if @@commands != {}
|
21
38
|
|
22
|
-
#{Rails.root}/
|
23
39
|
filename = "app/logic/#{logic_name}.logic"
|
24
40
|
logic_data = File.read(filename)
|
25
41
|
|
26
|
-
|
27
|
-
command = ''
|
42
|
+
command = nil
|
28
43
|
|
29
|
-
lines = logic_data.split("\n").map(&:rstrip).select { |l| l != '' }
|
44
|
+
lines = logic_data.split("\n").map(&:rstrip).select { |l| l != '' && !l.strip.start_with?('#') }
|
30
45
|
lines.each do |line|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
46
|
+
if line.start_with? ' '
|
47
|
+
raise "#{filename} is broken!" if command.nil?
|
48
|
+
|
49
|
+
@@commands[command] ||= []
|
50
|
+
# begin
|
51
|
+
@@commands[command] << Aristotle::Command.new(line.strip, @@conditions, @@actions)
|
52
|
+
# rescue => e
|
53
|
+
# raise e.message + ' in ' + filename
|
54
|
+
# end
|
55
|
+
else
|
38
56
|
command = line
|
39
|
-
elsif line.start_with?(' ')
|
40
|
-
found_lines << line.strip
|
41
57
|
end
|
42
58
|
end
|
43
|
-
@@commands[command] = found_lines if command != '' && found_lines.length > 0
|
44
59
|
end
|
45
60
|
|
46
61
|
def self.html_rules
|
47
|
-
|
48
|
-
@@commands.map do |command, lines|
|
49
|
-
"<strong>#{command}</strong><ul>#{lines.map{|l| "<li>- #{l.gsub(' if ', ' <strong style="color:blue">IF</strong> ').gsub(/'([^']+)'/, '<strong>\1</strong>')}</li>"}.join}</ul>"
|
50
|
-
end.join('<br>').html_safe
|
51
|
-
end
|
52
|
-
|
53
|
-
def process_condition(condition)
|
54
|
-
if @@conditions.has_key? condition
|
55
|
-
@@conditions[condition].call(@object)
|
56
|
-
else
|
57
|
-
raise "Condition not found: #{condition}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def do_action(action)
|
62
|
-
if @@actions.has_key? action
|
63
|
-
@@actions[action].call(@object)
|
64
|
-
else
|
65
|
-
raise "Action not found: #{action}"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def commands(logic_method)
|
70
|
-
self.class.load_commands
|
71
|
-
@@commands[logic_method] || []
|
72
|
-
end
|
73
|
-
|
74
|
-
def process(logic_method)
|
75
|
-
commands(logic_method).each do |command|
|
76
|
-
action, condition = command.split(' if ', 2)
|
77
|
-
|
78
|
-
if process_condition(condition)
|
79
|
-
# puts "Condition matched: #{condition}"
|
80
|
-
# puts "Doing action: #{action}"
|
81
|
-
return do_action(action)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
nil
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.is_everything_covered?
|
89
|
-
load_commands
|
90
|
-
not_covered = {}
|
91
|
-
@@commands.each do |logic_method, command|
|
92
|
-
command.each do |line|
|
93
|
-
action, condition = line.split(' if ', 2)
|
94
|
-
|
95
|
-
unless @@actions.has_key?(action)
|
96
|
-
not_covered[logic_method] ||= {actions: [], conditions: []}
|
97
|
-
not_covered[logic_method][:actions] << action
|
98
|
-
end
|
99
|
-
unless @@conditions.has_key?(condition)
|
100
|
-
not_covered[logic_method] ||= {actions: [], conditions: []}
|
101
|
-
not_covered[logic_method][:conditions] << condition
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
if not_covered != {}
|
107
|
-
not_covered.each do |request_method, data|
|
108
|
-
puts "\nclass #{self.to_s} < Aristotle::Logic"
|
109
|
-
puts " # #{request_method}:\n"
|
110
|
-
data[:actions].each do |action|
|
111
|
-
puts " action /#{action}/ do |#{logic_name}|\n\n end\n\n"
|
112
|
-
end
|
113
|
-
data[:conditions].each do |condition|
|
114
|
-
puts " condition /#{condition}/ do |#{logic_name}|\n\n end\n\n"
|
115
|
-
end
|
116
|
-
puts "end"
|
117
|
-
end
|
118
|
-
else
|
119
|
-
puts '-> Everything is covered!'
|
120
|
-
end
|
121
|
-
|
122
|
-
not_covered == {}
|
62
|
+
Aristotle::Presenter.new(self).html_rules
|
123
63
|
end
|
124
64
|
|
125
65
|
def self.logic_name
|
126
66
|
self.to_s.gsub(/Logic$/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
127
67
|
end
|
128
|
-
|
129
|
-
def self.descendants
|
130
|
-
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
131
|
-
end
|
132
68
|
end
|
133
69
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Aristotle
|
2
|
+
class Presenter
|
3
|
+
def initialize(klass)
|
4
|
+
@klass = klass
|
5
|
+
end
|
6
|
+
|
7
|
+
def html_rules
|
8
|
+
@klass.commands.map do |command, lines|
|
9
|
+
"<strong>#{command}</strong>"+
|
10
|
+
"<ul>"+
|
11
|
+
lines.map do |line|
|
12
|
+
"<li>- "+
|
13
|
+
line.action.gsub(/'([^']+)'/, '<strong>\1</strong>')+
|
14
|
+
" <strong style='color:blue'>IF</strong> "+
|
15
|
+
line.condition.gsub(/'([^']+)'/, '<strong>\1</strong>')+
|
16
|
+
"</li>"
|
17
|
+
end.join +
|
18
|
+
"</ul>"
|
19
|
+
end.join('<br>').html_safe
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/aristotle/utility.rb
CHANGED
@@ -1,15 +1,62 @@
|
|
1
1
|
module Aristotle
|
2
2
|
class Utility
|
3
3
|
def self.check_all
|
4
|
+
logic_objects.each_with_index do |logic_class, i|
|
5
|
+
puts "Checking #{logic_class}"
|
6
|
+
is_everything_covered_for? logic_class
|
7
|
+
puts if i > 0
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def self.logic_objects
|
14
|
+
init_logic_objects unless @logic_objects_initialized
|
15
|
+
|
16
|
+
ObjectSpace.each_object(Class).select { |klass| klass < Aristotle::Logic }
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.init_logic_objects
|
4
20
|
Dir[%w(app logic *.rb).join(File::SEPARATOR)].each do |file|
|
5
21
|
require Dir.pwd + File::SEPARATOR + file
|
6
22
|
end
|
23
|
+
@logic_objects_initialized = true
|
24
|
+
end
|
7
25
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
26
|
+
def self.is_everything_covered_for?(logic_class)
|
27
|
+
not_covered = {}
|
28
|
+
logic_class.commands.each do |logic_method, commands|
|
29
|
+
commands.each do |command|
|
30
|
+
unless command.has_action?
|
31
|
+
not_covered[logic_method] ||= {actions: [], conditions: []}
|
32
|
+
not_covered[logic_method][:actions] << command.action
|
33
|
+
end
|
34
|
+
unless command.has_condition?
|
35
|
+
not_covered[logic_method] ||= {actions: [], conditions: []}
|
36
|
+
not_covered[logic_method][:conditions] << command.condition
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
if not_covered != {}
|
42
|
+
not_covered.each do |request_method, data|
|
43
|
+
puts "\nclass #{self.to_s} < Aristotle::Logic"
|
44
|
+
puts " # #{request_method}:\n"
|
45
|
+
data[:actions].each do |action|
|
46
|
+
puts " action /#{action}/ do |#{logic_class.logic_name}|\n\n end\n\n"
|
47
|
+
end
|
48
|
+
data[:conditions].each do |condition|
|
49
|
+
puts " condition /#{condition}/ do |#{logic_class.logic_name}|\n\n end\n\n"
|
50
|
+
end
|
51
|
+
puts "end"
|
52
|
+
end
|
53
|
+
else
|
54
|
+
puts '-> Everything is covered!'
|
12
55
|
end
|
56
|
+
|
57
|
+
not_covered == {}
|
13
58
|
end
|
59
|
+
|
60
|
+
|
14
61
|
end
|
15
62
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aristotle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marius Andra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby business logic engine, inspired by Cucumber
|
14
14
|
email: marius@apprentus.com
|
@@ -19,7 +19,9 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- bin/aristotle
|
21
21
|
- lib/aristotle.rb
|
22
|
+
- lib/aristotle/command.rb
|
22
23
|
- lib/aristotle/logic.rb
|
24
|
+
- lib/aristotle/presenter.rb
|
23
25
|
- lib/aristotle/utility.rb
|
24
26
|
homepage: https://github.com/apprentus/aristotle
|
25
27
|
licenses:
|