expressive 0.0.8 → 0.0.9
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.
- data/Gemfile.lock +1 -1
- data/lib/expressive.rb +3 -1
- data/lib/expressive/version.rb +1 -1
- data/lib/extended_value.rb +21 -0
- data/lib/scope.rb +44 -31
- data/lib/webhook.rb +29 -0
- data/spec/expressive_spec.rb +37 -2
- data/spec/scope_spec.rb +50 -6
- metadata +6 -4
data/Gemfile.lock
CHANGED
data/lib/expressive.rb
CHANGED
@@ -3,6 +3,8 @@ require 'treetop'
|
|
3
3
|
require 'awesome_print'
|
4
4
|
require 'rest_client'
|
5
5
|
require File.join(File.dirname(__FILE__), 'scope')
|
6
|
+
require File.join(File.dirname(__FILE__), 'extended_value')
|
7
|
+
require File.join(File.dirname(__FILE__), 'webhook')
|
6
8
|
|
7
9
|
Treetop.load File.join(File.dirname(__FILE__), 'expressive_grammar.treetop')
|
8
10
|
|
@@ -18,7 +20,7 @@ module Expressive
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def self.all_symbols
|
21
|
-
%w(+ - * / = set sum post >= > < <= and or if date get put)
|
23
|
+
%w(+ - * / = set sum post >= > < <= and or if date get put lookup)
|
22
24
|
end
|
23
25
|
|
24
26
|
module Boolean
|
data/lib/expressive/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Expressive
|
2
|
+
|
3
|
+
class ExtendedValue
|
4
|
+
attr_accessor :setter, :adder
|
5
|
+
def initialize(property_name, scope)
|
6
|
+
@scope = scope
|
7
|
+
@property_name = property_name.to_s
|
8
|
+
|
9
|
+
@scope[@property_name] = self
|
10
|
+
end
|
11
|
+
|
12
|
+
def set(value)
|
13
|
+
setter.call value, @scope
|
14
|
+
end
|
15
|
+
|
16
|
+
def <<(value)
|
17
|
+
adder.call value, @scope
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/scope.rb
CHANGED
@@ -1,9 +1,25 @@
|
|
1
1
|
module Expressive
|
2
2
|
require 'json'
|
3
|
+
|
3
4
|
class Scope
|
5
|
+
attr_reader :lookups
|
4
6
|
def initialize(parent = {})
|
5
7
|
@parent = parent
|
6
8
|
@symbols = {}
|
9
|
+
@lookups = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_lookup_table(lookup_table_name, lookups)
|
13
|
+
@lookups[lookup_table_name] = {} unless @lookups.include?(lookup_table_name)
|
14
|
+
@lookups[lookup_table_name].merge!(lookups)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_lookup_function(lookup_function_name, passed_in_options, &func_proc)
|
18
|
+
@lookups[lookup_function_name] = [passed_in_options, func_proc]
|
19
|
+
end
|
20
|
+
|
21
|
+
def clear_lookup_tables
|
22
|
+
@lookups.clear
|
7
23
|
end
|
8
24
|
|
9
25
|
def [](name)
|
@@ -11,7 +27,20 @@ module Expressive
|
|
11
27
|
end
|
12
28
|
|
13
29
|
def []=(name, value)
|
14
|
-
|
30
|
+
if value
|
31
|
+
if value.is_a?(ExtendedValue)
|
32
|
+
@symbols[name] = value unless @symbols.include?(name)
|
33
|
+
else
|
34
|
+
current_value = @symbols[name]
|
35
|
+
if current_value and current_value.is_a?(ExtendedValue)
|
36
|
+
current_value.set(value)
|
37
|
+
else
|
38
|
+
@symbols[name] = value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
@symbols[name] = value
|
43
|
+
end
|
15
44
|
end
|
16
45
|
|
17
46
|
def merge(scope)
|
@@ -36,36 +65,6 @@ module Expressive
|
|
36
65
|
end
|
37
66
|
end
|
38
67
|
|
39
|
-
class Webhook
|
40
|
-
|
41
|
-
def initialize(verb, url, params, headers)
|
42
|
-
@verb, @url, @params, @headers = verb, url, params, headers
|
43
|
-
end
|
44
|
-
|
45
|
-
def execute
|
46
|
-
self.send(@verb)
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def post
|
52
|
-
headers = {:content_type => :json, :accept => :json}
|
53
|
-
headers = headers.merge(@headers) if @headers
|
54
|
-
RestClient.post(@url, @params.to_json, headers)
|
55
|
-
end
|
56
|
-
|
57
|
-
def get
|
58
|
-
headers = {:params => @params}
|
59
|
-
headers = headers.merge(@headers) if @headers
|
60
|
-
RestClient.get(@url, headers)
|
61
|
-
end
|
62
|
-
|
63
|
-
def put
|
64
|
-
RestClient.put(@url, @params)
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
68
|
class TopLevel < Scope
|
70
69
|
|
71
70
|
def initialize
|
@@ -75,6 +74,20 @@ module Expressive
|
|
75
74
|
scope[cells.first.text_value] = cells[1].eval(scope)
|
76
75
|
end
|
77
76
|
|
77
|
+
syntax('lookup') do |scope, cells|
|
78
|
+
lookup_result = scope.lookups[cells.first.text_value]
|
79
|
+
if lookup_result
|
80
|
+
key = cells[1].text_value[1..-2]
|
81
|
+
if lookup_result.is_a?(Hash)
|
82
|
+
lookup_result[key]
|
83
|
+
elsif lookup_result.is_a?(Array)
|
84
|
+
options = lookup_result.first
|
85
|
+
the_proc = lookup_result.last
|
86
|
+
the_proc.call(options, key)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
78
91
|
syntax('post') do |scope, cells|
|
79
92
|
perform_webhook(:post, scope, cells)
|
80
93
|
end
|
data/lib/webhook.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Expressive
|
2
|
+
class Webhook
|
3
|
+
|
4
|
+
def initialize(verb, url, params, headers)
|
5
|
+
@verb, @url, @params, @headers = verb, url, params, headers
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute
|
9
|
+
self.send(@verb)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def post
|
14
|
+
headers = {:content_type => :json, :accept => :json}
|
15
|
+
headers = headers.merge(@headers) if @headers
|
16
|
+
RestClient.post(@url, @params.to_json, headers)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get
|
20
|
+
headers = {:params => @params}
|
21
|
+
headers = headers.merge(@headers) if @headers
|
22
|
+
RestClient.get(@url, headers)
|
23
|
+
end
|
24
|
+
|
25
|
+
def put
|
26
|
+
RestClient.put(@url, @params)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/expressive_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe "Expressive" do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
describe "all_symbols" do
|
9
|
-
it { Expressive.all_symbols.should =~ %w(+ - * / = set sum get put post >= > < <= and or if date) }
|
9
|
+
it { Expressive.all_symbols.should =~ %w(+ - * / = set sum get put post >= > < <= and or if date lookup) }
|
10
10
|
end
|
11
11
|
|
12
12
|
describe "understands booleans" do
|
@@ -95,9 +95,10 @@ describe "Expressive" do
|
|
95
95
|
end
|
96
96
|
|
97
97
|
it "using multiple set commands" do
|
98
|
-
Expressive.run('(and (set vsi "vsi1234") (set vso "vso1234"))', @scope).should eql true
|
98
|
+
Expressive.run('(and (set vsi "vsi1234") (set vso "vso1234") (set vsbool true))', @scope).should eql true
|
99
99
|
@scope['vsi'].should eql 'vsi1234'
|
100
100
|
@scope['vso'].should eql 'vso1234'
|
101
|
+
@scope['vsbool'].should be_true
|
101
102
|
end
|
102
103
|
end
|
103
104
|
|
@@ -115,6 +116,40 @@ describe "Expressive" do
|
|
115
116
|
end
|
116
117
|
end
|
117
118
|
|
119
|
+
describe "understands using lookup tables" do
|
120
|
+
before(:each) do
|
121
|
+
@user1 = mock(:user, id:1, login: "user1", display_name: "User 1")
|
122
|
+
@user2 = mock(:user, id:2, login: "user2", display_name: "User 2")
|
123
|
+
@scope.add_lookup_table("users", @user1.login => @user1, @user2.login => @user2)
|
124
|
+
@scope.add_lookup_table("users", "x_current" => @user2)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "will return a value from a lookup table" do
|
128
|
+
Expressive.run('(lookup users "x_current")', @scope).should eql @user2
|
129
|
+
Expressive.run('(lookup users "user1")', @scope).should eql @user1
|
130
|
+
end
|
131
|
+
it "will set multiple values based on results of a lookup" do
|
132
|
+
@owned_by_ext_value = Expressive::ExtendedValue.new(:x_owned_by, @scope)
|
133
|
+
@owned_by_ext_value.setter = Proc.new do |value, scope|
|
134
|
+
scope["owned_by_id"] = value.id
|
135
|
+
scope["owned_by_type"] = value.class.to_s
|
136
|
+
end
|
137
|
+
|
138
|
+
Expressive.run('(set x_owned_by (lookup users "x_current"))', @scope)
|
139
|
+
@scope["owned_by_id"].should eql @user2.id
|
140
|
+
@scope["owned_by_type"].should eql "RSpec::Mocks::Mock"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "understands using lookup functions" do
|
145
|
+
it "should perform the lookup function (add account and reverse login)" do
|
146
|
+
@scope.add_lookup_function("account_reverse_login", account: "ea") do |options, login|
|
147
|
+
"#{options[:account]}-#{login.reverse}"
|
148
|
+
end
|
149
|
+
Expressive.run('(lookup account_reverse_login "ijonas")', @scope).should eql "ea-sanoji"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
118
153
|
describe "understands web-hook statements" do
|
119
154
|
context "put" do
|
120
155
|
it_should_behave_like "a webhook", :put
|
data/spec/scope_spec.rb
CHANGED
@@ -1,12 +1,56 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
|
3
|
+
module Expressive
|
4
|
+
describe TopLevel do
|
5
|
+
|
6
|
+
describe "#to_hash" do
|
7
|
+
it "return only the hash data" do
|
8
|
+
@scope = TopLevel.new
|
9
|
+
@scope["hello"] = "world"
|
10
|
+
@scope.to_hash.should eql({"hello" => "world"})
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ExtendedValue do
|
17
|
+
it "sets the multiple values of a ExtendedValue" do
|
18
|
+
@scope = TopLevel.new
|
19
|
+
|
20
|
+
@owned_by_ext_value = ExtendedValue.new(:x_owned_by, @scope)
|
21
|
+
@owned_by_ext_value.setter = Proc.new do |value, scope|
|
22
|
+
scope["owned_by_id"] = value.id
|
23
|
+
scope["owned_by_type"] = value.class.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
@scope["x_owned_by"] = mock(:current_user, id: 1)
|
27
|
+
@scope["owned_by_id"].should eql 1
|
28
|
+
@scope["owned_by_type"].should eql "RSpec::Mocks::Mock"
|
29
|
+
|
30
|
+
|
31
|
+
@current_state_ext_value = ExtendedValue.new(:x_current_state, @scope)
|
32
|
+
@current_state_ext_value.setter = Proc.new do |value, scope|
|
33
|
+
scope["current_state"] = value.state
|
34
|
+
scope["current_state_id"] = value.id
|
35
|
+
end
|
36
|
+
|
37
|
+
@scope["x_current_state"] = mock(:some_state, id: 1, state: "Pending")
|
38
|
+
@scope["current_state_id"].should eql 1
|
39
|
+
@scope["current_state"].should eql "Pending"
|
40
|
+
end
|
41
|
+
it "add values to a Set construct" do
|
42
|
+
@scope = TopLevel.new
|
43
|
+
|
44
|
+
@participating_teams_ext_value = ExtendedValue.new(:x_participating_teams, @scope)
|
45
|
+
@participating_teams_ext_value.adder = Proc.new do |value, scope|
|
46
|
+
scope["participating_teams"] << value.id unless scope["participating_teams"].include?(value.id)
|
47
|
+
end
|
48
|
+
|
49
|
+
@scope["participating_teams"] = [1]
|
50
|
+
@scope["x_participating_teams"] << mock(:some_team, id: 2, display_name: "The B-Team")
|
51
|
+
@scope["x_participating_teams"] << mock(:some_team, id: 2, display_name: "The B-Team")
|
52
|
+
@scope["participating_teams"].should =~ [1,2]
|
4
53
|
|
5
|
-
describe "to_hash" do
|
6
|
-
it "return only the hash data" do
|
7
|
-
@scope = Expressive::TopLevel.new
|
8
|
-
@scope["hello"] = "world"
|
9
|
-
@scope.to_hash.should eql({"hello" => "world"})
|
10
54
|
end
|
11
55
|
end
|
12
56
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: expressive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruby_gntp
|
@@ -273,7 +273,9 @@ files:
|
|
273
273
|
- lib/expressive.rb
|
274
274
|
- lib/expressive/version.rb
|
275
275
|
- lib/expressive_grammar.treetop
|
276
|
+
- lib/extended_value.rb
|
276
277
|
- lib/scope.rb
|
278
|
+
- lib/webhook.rb
|
277
279
|
- spec/expressive_spec.rb
|
278
280
|
- spec/scope_spec.rb
|
279
281
|
- spec/spec_helper.rb
|
@@ -292,7 +294,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
292
294
|
version: '0'
|
293
295
|
segments:
|
294
296
|
- 0
|
295
|
-
hash:
|
297
|
+
hash: 275595429222270530
|
296
298
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
297
299
|
none: false
|
298
300
|
requirements:
|
@@ -301,7 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
301
303
|
version: '0'
|
302
304
|
segments:
|
303
305
|
- 0
|
304
|
-
hash:
|
306
|
+
hash: 275595429222270530
|
305
307
|
requirements: []
|
306
308
|
rubyforge_project:
|
307
309
|
rubygems_version: 1.8.23
|