rubel 0.0.1
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/.gitignore +19 -0
- data/.rspec +2 -0
- data/README.md +2 -0
- data/lib/rubel/base.rb +6 -0
- data/lib/rubel/core.rb +66 -0
- data/lib/rubel/error_reporter.rb +7 -0
- data/lib/rubel/functions/defaults.rb +136 -0
- data/lib/rubel/runtime/console.rb +42 -0
- data/lib/rubel/runtime/loader.rb +30 -0
- data/lib/rubel/runtime/sandbox.rb +60 -0
- data/lib/rubel.rb +8 -0
- data/spec/integration/rubel_spec.rb +97 -0
- data/spec/spec_helper.rb +14 -0
- metadata +61 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/README.md
ADDED
data/lib/rubel/base.rb
ADDED
data/lib/rubel/core.rb
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Rubel
|
|
2
|
+
module Core
|
|
3
|
+
# query - The String or Proc to be executed
|
|
4
|
+
def execute(query = nil)
|
|
5
|
+
|
|
6
|
+
if query.is_a?(::String)
|
|
7
|
+
query = sanitized_proc(query)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
instance_exec(&query)
|
|
11
|
+
#rescue => e
|
|
12
|
+
# ::Rubel::ErrorReporter.new(e, query)
|
|
13
|
+
end
|
|
14
|
+
alias query execute
|
|
15
|
+
|
|
16
|
+
# Sanitize a string from Ruby injection.
|
|
17
|
+
#
|
|
18
|
+
# It removes "::" from the string to prevent people to access
|
|
19
|
+
# classes outside Runtime::Sandbox
|
|
20
|
+
#
|
|
21
|
+
#
|
|
22
|
+
def sanitize!(string)
|
|
23
|
+
string.gsub!('::', '')
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Sanitize a string from Ruby injection.
|
|
27
|
+
#
|
|
28
|
+
# It removes "::" from the string to prevent people to access
|
|
29
|
+
# classes outside Runtime::Sandbox
|
|
30
|
+
#
|
|
31
|
+
#
|
|
32
|
+
def sanitized_proc(string)
|
|
33
|
+
sanitize!(string)
|
|
34
|
+
eval("lambda { #{string} }")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns method name as a Symbol if args are empty
|
|
38
|
+
# or a Proc calling method_name with (evaluated) args [1].
|
|
39
|
+
#
|
|
40
|
+
# @example
|
|
41
|
+
# r$: MAP( [foo, bar], to_s )
|
|
42
|
+
# # First it converts foo, bar, to_s to symbols. Then MAP will call :to_s on [:foo, :bar]
|
|
43
|
+
# # Thus it is equivalent to: [:foo, :bar].map(&:to_s)
|
|
44
|
+
#
|
|
45
|
+
# @example
|
|
46
|
+
#
|
|
47
|
+
# r$: MAP( [0.123456, 0.98765], # the objects
|
|
48
|
+
# r$: round( SUM(1,2) ) ) # instruction to round by 3.
|
|
49
|
+
# r$: # => Proc.new { round( 3 ) }
|
|
50
|
+
#
|
|
51
|
+
#
|
|
52
|
+
# @return [Proc] A Proc with a method call to *name* and arguments *args*.
|
|
53
|
+
# If *args* are Rubel statements, they will be evaluated beforehand.
|
|
54
|
+
# This makes it possible to add objects and rubel statements to method calls.
|
|
55
|
+
#
|
|
56
|
+
# @return [Symbol] The name itself. This is useful for LOOKUPs. E.g. USER( test_123 )
|
|
57
|
+
#
|
|
58
|
+
def method_missing(name, *args)
|
|
59
|
+
if !(args.nil? || args.length == 0)
|
|
60
|
+
::Proc.new { self.send(name, *args) }
|
|
61
|
+
else
|
|
62
|
+
name
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module Rubel
|
|
2
|
+
module Functions
|
|
3
|
+
# Default/standard functions like SUM,AVG,COUNT,etc that operate
|
|
4
|
+
# on numbers and are application independent.
|
|
5
|
+
module Defaults
|
|
6
|
+
def MAP(elements, attr_name)
|
|
7
|
+
elements = [elements] unless elements.is_a?(::Array)
|
|
8
|
+
|
|
9
|
+
elements.tap(&:flatten!).map! do |a|
|
|
10
|
+
if attr_name.respond_to?(:call)
|
|
11
|
+
a.instance_exec(&attr_name)
|
|
12
|
+
else
|
|
13
|
+
# to_s imported, for when MAP(..., demand) demand comes through method_missing (as a symbol)
|
|
14
|
+
a.instance_eval(attr_name.to_s)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
elements.length <= 1 ? (elements.first || 0.0) : elements
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns how many values. Removes nil values, but does
|
|
21
|
+
# not remove duplicates.
|
|
22
|
+
#
|
|
23
|
+
# @example Basic useage
|
|
24
|
+
# COUNT(1) # => 1
|
|
25
|
+
# COUNT(1,2) # => 1
|
|
26
|
+
#
|
|
27
|
+
# @example with converters
|
|
28
|
+
# COUNT(L(foo,bar)) # => 2
|
|
29
|
+
#
|
|
30
|
+
# @example multiple LOOKUPs (does not remove duplicates)
|
|
31
|
+
# COUNT(L(foo,bar), L(foo)) # => 3
|
|
32
|
+
# # However: (LOOKUP removes duplicates)
|
|
33
|
+
# COUNT(L(foo,bar,foo), L(f)) # => 2
|
|
34
|
+
#
|
|
35
|
+
# @example nil values are removed (do not count)
|
|
36
|
+
# COUNT(1,nil,2) # => 2
|
|
37
|
+
#
|
|
38
|
+
# @param [Numeric,Array] *values one or multiple values or arrays
|
|
39
|
+
# @return [Numeric] The element count.
|
|
40
|
+
#
|
|
41
|
+
def COUNT(*values)
|
|
42
|
+
values.flatten!
|
|
43
|
+
values.compact!
|
|
44
|
+
|
|
45
|
+
values.length
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns the average of all number (ignores nil values).
|
|
49
|
+
#
|
|
50
|
+
# @example
|
|
51
|
+
# AVG(1,2) # => 1.5
|
|
52
|
+
# AVG(1,2,3) # => 2
|
|
53
|
+
# AVG(1,nil,nil,2) # => 1.5
|
|
54
|
+
#
|
|
55
|
+
# @param [Numeric,Array] *values one or multiple values or arrays
|
|
56
|
+
# @return [Numeric] The average of all values
|
|
57
|
+
#
|
|
58
|
+
def AVG(*values)
|
|
59
|
+
values.flatten!
|
|
60
|
+
values.compact!
|
|
61
|
+
SUM(values) / COUNT(values)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Returns the sum of all numbers (ignores nil values).
|
|
65
|
+
#
|
|
66
|
+
# @example
|
|
67
|
+
# SUM(1,2) # => 3
|
|
68
|
+
# SUM(1,2,3) # => 6
|
|
69
|
+
# SUM(1) # => 1
|
|
70
|
+
# SUM(1,nil) # => 1
|
|
71
|
+
#
|
|
72
|
+
# @param [Numeric,Array] *values one or multiple values or arrays
|
|
73
|
+
# @return [Numeric] The average of all values
|
|
74
|
+
#
|
|
75
|
+
def SUM(*values)
|
|
76
|
+
values.flatten!
|
|
77
|
+
values.compact!
|
|
78
|
+
values.inject(0) {|h,v| h + v }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Multiplies all numbers (ignores nil values).
|
|
82
|
+
#
|
|
83
|
+
# @example
|
|
84
|
+
# PRODUCT(1,2) # => 2 (1*2)
|
|
85
|
+
# PRODUCT(1,2,3) # => 6 (1*2*3)
|
|
86
|
+
# PRODUCT(1) # => 1
|
|
87
|
+
# PRODUCT(1,nil) # => 1
|
|
88
|
+
#
|
|
89
|
+
# @param [Numeric,Array] *values one or multiple values or arrays
|
|
90
|
+
# @return [Numeric] The average of all values
|
|
91
|
+
#
|
|
92
|
+
def PRODUCT(*values)
|
|
93
|
+
values.flatten!
|
|
94
|
+
values.compact!
|
|
95
|
+
values.inject(1) {|total,value| total = total * value}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Divides the first with the second.
|
|
100
|
+
#
|
|
101
|
+
# @example
|
|
102
|
+
# DIVIDE(1,2) # => 0.5
|
|
103
|
+
# DIVIDE(1,2,3,4) # => 0.5 # only takes the first two numbers
|
|
104
|
+
# DIVIDE([1,2]) # => 0.5
|
|
105
|
+
# DIVIDE([1],[2]) # => 0.5
|
|
106
|
+
# DIVIDE(1,2) # => 0.5
|
|
107
|
+
#
|
|
108
|
+
# @example Watch out doing normal arithmetics (outside DIVIDE)
|
|
109
|
+
# DIVIDE(2,3) # => 0.66
|
|
110
|
+
# # (divideing integers gets you elimentary school output. 2 / 3 = 0 with remainder 2)
|
|
111
|
+
# 2 / 3 # => 0
|
|
112
|
+
# 2 % 3 # => 2 # % = modulo (what is the remainder)
|
|
113
|
+
# 2.0 / 3 # => 0.66 If one number is a float it works as expected
|
|
114
|
+
# 2 / 3.0 # => 0.66 If one number is a float it works as expected
|
|
115
|
+
#
|
|
116
|
+
# @example Exceptions
|
|
117
|
+
# DIVIDE(nil, 1) # => 0.0
|
|
118
|
+
# DIVIDE(0.0, 1) # => 0.0 and not NaN
|
|
119
|
+
# DIVIDE(0, 1) # => 0.0 and not NaN
|
|
120
|
+
# DIVIDE(1.0,0.0) # => Infinity
|
|
121
|
+
#
|
|
122
|
+
# @param [Numeric,Array] *values one or multiple values or arrays. But only the first two are taken.
|
|
123
|
+
# @return [Numeric] The average of all values
|
|
124
|
+
#
|
|
125
|
+
def DIVIDE(*values)
|
|
126
|
+
a,b = values.tap(&:flatten!)
|
|
127
|
+
|
|
128
|
+
if a.nil? || a.to_f == 0.0
|
|
129
|
+
0.0
|
|
130
|
+
else
|
|
131
|
+
a.to_f / b
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Rubel
|
|
2
|
+
module Runtime
|
|
3
|
+
# Used for GQL console
|
|
4
|
+
class Console # < BasicObject
|
|
5
|
+
include ::Rubel::Core
|
|
6
|
+
|
|
7
|
+
# A Pry prompt that logs what user enters to a log file
|
|
8
|
+
# so it can easily be copy pasted by users.
|
|
9
|
+
#
|
|
10
|
+
# DOES NOT WORK :( couldn't make it work
|
|
11
|
+
# class LoggingPrompt
|
|
12
|
+
# include Readline
|
|
13
|
+
#
|
|
14
|
+
# def readline(prompt = "GQL: ", add_hist = true)
|
|
15
|
+
# @logger ||= Logger.new('gqlconsole/prompt.log', 'daily')
|
|
16
|
+
# super(prompt, add_hist).tap do |line|
|
|
17
|
+
# @logger.info(line)
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
# end
|
|
21
|
+
|
|
22
|
+
# Prints string directly
|
|
23
|
+
RESULT_PRINTER = proc do |output, value|
|
|
24
|
+
if value.is_a?(String)
|
|
25
|
+
output.puts value
|
|
26
|
+
else
|
|
27
|
+
::Pry::DEFAULT_PRINT.call(output, value)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Starts the Pry console
|
|
32
|
+
def console
|
|
33
|
+
require 'pry'
|
|
34
|
+
puts "** Console Loaded"
|
|
35
|
+
::Pry.start(self,
|
|
36
|
+
# input: LoggingPrompt.new,
|
|
37
|
+
prompt: proc { |_, nest_level| "GQL: " },
|
|
38
|
+
print: RESULT_PRINTER)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Rubel
|
|
2
|
+
module Runtime
|
|
3
|
+
# Loader determines which runtime to load, based on RAILS_ENV.
|
|
4
|
+
# For production and test environment uses {Rubel::Runtime::Sandbox}.
|
|
5
|
+
# In all other cases {Rubel::Runtime::Console}
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
#
|
|
9
|
+
# Rubel::Runtime::Loader.runtime.new
|
|
10
|
+
#
|
|
11
|
+
# @example For your own Runtime class
|
|
12
|
+
#
|
|
13
|
+
# class MyRuntime < Rubel::Runtime::Loader.runtime
|
|
14
|
+
# include ::Rubel::Core
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
class Loader
|
|
18
|
+
|
|
19
|
+
def self.runtime
|
|
20
|
+
case ENV['RAILS_ENV']
|
|
21
|
+
when 'production' then ::Rubel::Runtime::Sandbox
|
|
22
|
+
when 'test' then ::Rubel::Runtime::Sandbox
|
|
23
|
+
when 'development' then ::Rubel::Runtime::Console
|
|
24
|
+
else ::Rubel::Runtime::Console
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Rubel
|
|
2
|
+
module Runtime
|
|
3
|
+
# Sandbox is the default runtime for production environments.
|
|
4
|
+
# It has some basic protection against ruby code injection.
|
|
5
|
+
#
|
|
6
|
+
# Sandbox is a {BasicObject} so it lives outside the default namespace.
|
|
7
|
+
# To access outside classes and modules you are forced to use "::" as
|
|
8
|
+
# namespace.
|
|
9
|
+
#
|
|
10
|
+
# @example Extending Runtime::Sandbox
|
|
11
|
+
#
|
|
12
|
+
# class MySandbox < Rubel::Runtime::Sandbox
|
|
13
|
+
# include ::MyModule::MyClass
|
|
14
|
+
#
|
|
15
|
+
# def hello_world
|
|
16
|
+
# ::Kernel.puts "hello world"
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# def create_blog_post
|
|
20
|
+
# ::BlogPost.create(:title => 'hello world')
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# @example Protection against ruby injection:
|
|
25
|
+
#
|
|
26
|
+
# r = Rubel::Runtime::Sandbox.new
|
|
27
|
+
# r.execute lambda { system('say hello') } # NoMethodError 'system'
|
|
28
|
+
# r.execute lambda { Object.new.system('say hello') } # Constant Object not found
|
|
29
|
+
#
|
|
30
|
+
# @example Protection against ruby injection does not work in this case:
|
|
31
|
+
# r.execute lambda { ::Object.new.system('say hello') }
|
|
32
|
+
# # However, passing query as String does basic string sanitizing
|
|
33
|
+
# r.execute "::Object.new.system('say hello')"
|
|
34
|
+
# # This can be circumvented:
|
|
35
|
+
# r.execute "#{(':'+':'+'Object').constantize.new.system('say hello')"
|
|
36
|
+
#
|
|
37
|
+
# # If you have rubel functions that use instance_eval for objects.
|
|
38
|
+
# r.execute lambda { MAP([0.1234, 2.12], "round(1) * 3.0; system('say hello);") }
|
|
39
|
+
#
|
|
40
|
+
class Sandbox < BasicObject
|
|
41
|
+
include ::Rubel::Core
|
|
42
|
+
|
|
43
|
+
# BasicObject does not contain {Kernel} methods, so we add the
|
|
44
|
+
# most important manually:
|
|
45
|
+
|
|
46
|
+
# make -> {} and lambda {} work when included as BasicObject
|
|
47
|
+
def lambda(&block)
|
|
48
|
+
::Kernel.lambda(&block)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def puts(str)
|
|
52
|
+
::Kernel.puts(str)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def sanitize!(string)
|
|
56
|
+
string.gsub!('::', '')
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
data/lib/rubel.rb
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
require_relative 'rubel/version'
|
|
2
|
+
require_relative 'rubel/core'
|
|
3
|
+
require_relative 'rubel/error_reporter'
|
|
4
|
+
require_relative 'rubel/runtime/sandbox'
|
|
5
|
+
require_relative 'rubel/runtime/console'
|
|
6
|
+
require_relative 'rubel/runtime/loader'
|
|
7
|
+
require_relative 'rubel/functions/defaults'
|
|
8
|
+
require_relative 'rubel/base'
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe do
|
|
4
|
+
it "should spec" do
|
|
5
|
+
true.should be_true
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context "Runtime::Loader" do
|
|
9
|
+
after do
|
|
10
|
+
ENV['RAILS_ENV'] = 'test'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should load Sandbox in test" do
|
|
14
|
+
ENV['RAILS_ENV'] = 'test'
|
|
15
|
+
Rubel::Runtime::Loader.runtime.should == Rubel::Runtime::Sandbox
|
|
16
|
+
end
|
|
17
|
+
it "should load Sandbox in production" do
|
|
18
|
+
ENV['RAILS_ENV'] = 'production'
|
|
19
|
+
Rubel::Runtime::Loader.runtime.should == Rubel::Runtime::Sandbox
|
|
20
|
+
end
|
|
21
|
+
it "should load Console in development" do
|
|
22
|
+
ENV['RAILS_ENV'] = 'development'
|
|
23
|
+
Rubel::Runtime::Loader.runtime.should == Rubel::Runtime::Console
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "default" do
|
|
28
|
+
before do
|
|
29
|
+
ENV['RAILS_ENV'] = 'test'
|
|
30
|
+
@rubel = Rubel::Base.new
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def execute(obj)
|
|
34
|
+
@rubel.execute(obj)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should execute "SUM(1,2,3)"' do
|
|
38
|
+
execute("SUM(1,2,3)").should == 6
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should execute lambda { SUM(1,2,3) }" do
|
|
42
|
+
execute(lambda { SUM(1,2,3) }).should == 6
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should execute Proc.new { SUM(1,2,3) }" do
|
|
46
|
+
execute(Proc.new { SUM(1,2,3) }).should == 6
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should execute" do
|
|
50
|
+
execute("5.124.round(SUM(1))").should == 5.1
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should execute MAP" do
|
|
54
|
+
execute("MAP([5.124], round(SUM(1)))").should == 5.1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Disabled block support. looks cool, but does not work
|
|
58
|
+
# with method_missing, etc. So rather confusing.
|
|
59
|
+
#
|
|
60
|
+
# it "should execute as do SUM(1,2,3) end" do
|
|
61
|
+
# execute do
|
|
62
|
+
# SUM(1,2,3)
|
|
63
|
+
# end.should == 6
|
|
64
|
+
# end
|
|
65
|
+
#
|
|
66
|
+
# it "should execute as { SUM(1,2,3) }" do
|
|
67
|
+
# execute{SUM(1,2,3)}.should == 6
|
|
68
|
+
# end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "sandbox" do
|
|
72
|
+
before { @sandbox = Rubel::Runtime::Sandbox.new }
|
|
73
|
+
it "should *not* restrict from accessing classes." do
|
|
74
|
+
lambda {
|
|
75
|
+
@sandbox.execute(-> { File.new })
|
|
76
|
+
}.should_not raise_error(NameError)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should restrict from accessing classes" do
|
|
80
|
+
lambda {
|
|
81
|
+
@sandbox.new.execute('Kernel.puts("hacked")')
|
|
82
|
+
}.should raise_error(NameError)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should restrict from accessing classes with ::" do
|
|
86
|
+
lambda {
|
|
87
|
+
@sandbox.new.execute('::Kernel.puts("hacked")')
|
|
88
|
+
}.should raise_error(NameError)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should return symbols for method_missing" do
|
|
92
|
+
@sandbox.execute(-> { foo }).should == :foo
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
|
3
|
+
# Require this file using `require "spec_helper.rb"` to ensure that it is only
|
|
4
|
+
# loaded once.
|
|
5
|
+
#
|
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
7
|
+
|
|
8
|
+
require 'rubel'
|
|
9
|
+
|
|
10
|
+
RSpec.configure do |config|
|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
|
12
|
+
config.run_all_when_everything_filtered = true
|
|
13
|
+
config.filter_run :focus
|
|
14
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rubel
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- hasclass
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-04-28 00:00:00.000000000 Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: ruby enterprise language
|
|
15
|
+
email:
|
|
16
|
+
- sebi.burkhard@gmail.com
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- .gitignore
|
|
22
|
+
- .rspec
|
|
23
|
+
- README.md
|
|
24
|
+
- lib/rubel.rb
|
|
25
|
+
- lib/rubel/base.rb
|
|
26
|
+
- lib/rubel/core.rb
|
|
27
|
+
- lib/rubel/error_reporter.rb
|
|
28
|
+
- lib/rubel/functions/defaults.rb
|
|
29
|
+
- lib/rubel/runtime/console.rb
|
|
30
|
+
- lib/rubel/runtime/loader.rb
|
|
31
|
+
- lib/rubel/runtime/sandbox.rb
|
|
32
|
+
- spec/integration/rubel_spec.rb
|
|
33
|
+
- spec/spec_helper.rb
|
|
34
|
+
homepage: http://hasclass.com/rubel
|
|
35
|
+
licenses: []
|
|
36
|
+
post_install_message:
|
|
37
|
+
rdoc_options: []
|
|
38
|
+
require_paths:
|
|
39
|
+
- lib
|
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
|
+
none: false
|
|
48
|
+
requirements:
|
|
49
|
+
- - ! '>='
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '0'
|
|
52
|
+
requirements: []
|
|
53
|
+
rubyforge_project:
|
|
54
|
+
rubygems_version: 1.8.11
|
|
55
|
+
signing_key:
|
|
56
|
+
specification_version: 3
|
|
57
|
+
summary: A dsl for excel-like formulas to run as regular rubycode. E.g. SUM(MAP(KEY_ACCOUNTS(),
|
|
58
|
+
revenue))
|
|
59
|
+
test_files:
|
|
60
|
+
- spec/integration/rubel_spec.rb
|
|
61
|
+
- spec/spec_helper.rb
|