formula_eval 0.0.1 → 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.
data/Rakefile CHANGED
@@ -11,6 +11,9 @@ begin
11
11
  gem.homepage = "http://github.com/mharris717/formula_eval"
12
12
  gem.authors = ["Mike Harris"]
13
13
  gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_dependency 'mharris_ext'
15
+ gem.add_dependency 'nested_hash_tricks'
16
+ gem.add_dependency 'safe_eval'
14
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
18
  end
16
19
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
@@ -1,55 +1,134 @@
1
- class CalculatingCollection
1
+
2
+
3
+ class Hash
4
+ def each_with_str_key
5
+ each do |k,v|
6
+ yield(k.to_s,v)
7
+ end
8
+ end
9
+ def nested_hash_set(*args)
10
+ args = args.flatten
11
+ KeyParts.with_parts(args[0..-2],:array => true) do |start,lst,mult|
12
+ start.each { |k| self[k] ||= {} }
13
+ self[lst] = args[-1]
14
+ end
15
+ end
16
+ end
17
+
18
+ class WrappingCollection
2
19
  attr_accessor :coll
3
20
  include FromHash
21
+ def method_missing(sym,*args,&b)
22
+ coll.send(sym,*args,&b)
23
+ end
24
+ def user_coll
25
+ coll.user_coll
26
+ end
27
+ fattr(:user_coll_last_calc_dt) do
28
+ user_coll.save! unless user_coll.last_calc_dt
29
+ user_coll.last_calc_dt
30
+ end
31
+ end
32
+
33
+ class CalculatingCollection < WrappingCollection
4
34
  fattr(:column_hash) do
5
- res = {}
6
- res[:zzz] = lambda { |doc| (doc['abc']||0).to_i + 7 }
7
- res[:xyz] = FormulaEval.new(:formula => '=(abc||0)+8')
8
- res[:percs] = FormulaEval.new(:formula => '=pension.perc')
9
- res[:percs2] = FormulaEval.new(:formula => '=pension.perc * 2.0')
10
- res['pension.just_perc'] = FormulaEval.new(:formula => '=perc')
11
- res['pension.just_perc_plus'] = FormulaEval.new(:formula => '=perc+1')
12
- res['pension.perc_plus_salary'] = FormulaEval.new(:formula => '=perc+salary')
13
- res
35
+ {}
36
+ end
37
+ fattr(:constants_hash) do
38
+ {}
39
+ end
40
+ def add_constant_column(name,formula)
41
+ arr = eval(formula).to_a
42
+ constants_hash[name] = arr
43
+ end
44
+ def add_column(name,blk)
45
+ blk = FormulaEval.new(:formula => blk, :coll => coll) if blk.kind_of?(String)
46
+ self.column_hash[name.to_s] = blk
47
+ end
48
+ def cleaned_doc(doc)
49
+ column_hash.keys.each do |k|
50
+ doc.dot_set(k,nil)
51
+ end
52
+ doc
14
53
  end
15
- def enriched_doc(doc)
16
- column_hash.each do |col,blk|
17
- # mylog 'enriched_doc', :col => col, :blk_class => blk.class, :doc => doc
18
- if col.to_s.split('.').size == 1
54
+ def constants_enriched_doc(doc,ops)
55
+ constants_hash.each do |col,vals|
56
+ vals = vals.to_a
57
+ KeyParts.with_parts(col) do |start,lst,mult|
58
+ if mult
59
+ doc[start] ||= []
60
+ vals.each_with_index do |val,i|
61
+ field = "#{start}.#{i}.#{lst}"
62
+ doc.dot_set(field,val)
63
+ end
64
+ elsif ops[:row_index]
65
+ doc[col] = vals[ops[:row_index]]
66
+ end
67
+ end
68
+ end
69
+ doc
70
+ end
71
+ def calc_enriched_doc(doc,ops)
72
+ doc = cleaned_doc(doc)
73
+ column_hash.each_with_str_key do |col,blk|
74
+ if KeyParts.single?(col)
19
75
  val = blk.call(doc)
20
- mylog 'dot_set',:col => col, :val => val, :doc => doc
21
- doc.dot_set(col.to_s,val)
76
+ doc.dot_set(col,val)
22
77
  else
23
- base = col.to_s.split('.')[0..-2].join(".")
24
- obj = MultiEval.get_nested(doc,base)
25
- val = blk.call(obj)
26
- mylog 'dot_set',:col => col, :val => val, :doc => doc, :obj => obj
27
- doc.dot_set(col.to_s,val)
78
+ doc.dot_set(col) do |obj|
79
+ multi = MultiEval.new(:objs => [obj,doc])
80
+ blk.call(multi)
81
+ end
28
82
  end
29
83
  end
30
84
  doc.to_unwrapped
31
85
  end
32
- def save(doc,ops={})
33
- mylog 'calc_save', :doc => doc, :doc_class => doc.class, :unwrapped => doc.to_unwrapped.class
34
- coll.save(enriched_doc(doc),ops)
86
+ def enriched_doc(doc,other_ops={})
87
+ doc = constants_enriched_doc(doc,other_ops)
88
+ doc = calc_enriched_doc(doc,other_ops)
89
+ end
90
+ def keys
91
+ ks = column_hash.keys.map { |x| x.split('.').first }.uniq
92
+ coll.keys.make_last(ks)
93
+ end
94
+ def save(doc,ops={},other_ops={})
95
+ doc = enriched_doc(doc,other_ops)
96
+ doc.nested_hash_set '_admin','last_calc_dt',Time.now
97
+
98
+ res = coll.save(doc,ops)
99
+ doc[:_id] = res
100
+ doc
35
101
  end
36
102
  def update_calcs!
37
- find({},{:limit => 9999}).each do |row|
38
- save(row)
103
+ end
104
+ def update_calcs_real!
105
+ constants_max = constants_hash.values.map { |x| x.to_a.size }.max || 0
106
+ find({},{:limit => 9999}).each_with_index do |row,i|
107
+ save(row,{},:row_index => i)
108
+ end
109
+ if constants_max > count
110
+ (count...constants_max).each do |i|
111
+ save({},{},:row_index => i)
112
+ end
39
113
  end
114
+ rescue => exp
115
+ mylog 'update_calcs', :trace => exp.backtrace.join("\n"), :message => exp.message
116
+ raise exp
40
117
  end
41
118
  def update_row(row_id,fields)
42
- row = (row_id == 'NEW') ? {} : find_by_id(row_id)
43
- raise "can't find row #{row_id} #{row_id.class} in coll #{name}. Count is #{find.count} IDs are "+find.to_a.map { |x| x['_id'] }.inspect + "Trying to update with #{fields.inspect}" unless row
44
- fields.each do |k,v|
45
- row.dot_set(k,mongo_value(v))
46
- row.delete(k) if v.blank?
47
- end
48
- row = enriched_doc(row)
49
- save(row)
50
- row
119
+ row = coll.update_row(row_id,fields)
120
+ mylog 'calc_update_row', :row => row, :coll => coll.class
121
+ row = save(row)
51
122
  end
52
- def method_missing(sym,*args,&b)
53
- coll.send(sym,*args,&b)
123
+ def needs_calc?(doc)
124
+ doc_dt = doc['_admin'].andand['last_calc_dt'] || Time.local(1970,1,1)
125
+ user_coll_last_calc_dt > doc_dt
126
+ end
127
+ def find(selector={},ops={})
128
+ res = coll.find(selector,ops)
129
+ if res.respond_to?(:each)
130
+ res.select { |doc| needs_calc?(doc) }.each { |doc| save(doc) }
131
+ end
132
+ res
54
133
  end
55
134
  end
@@ -27,9 +27,10 @@ class MultiEval
27
27
  end
28
28
  def method_missing(sym,*args,&b)
29
29
  objs.each do |obj|
30
- if obj.respond_to?(sym)
30
+ if obj.smart_respond_to?(sym,args)
31
31
  res = obj.send(sym,*args,&b)
32
- return MultiEval.new(:objs => [res]+without_obj(obj)) if res
32
+ #return MultiEval.new(:objs => [res]+without_obj(obj)) #if res
33
+ return res if res
33
34
  end
34
35
  end
35
36
  raise 'none respond'
@@ -48,9 +49,31 @@ class MultiEval
48
49
  objs.first * x
49
50
  end
50
51
  def self.get_nested(obj,method_str)
51
- other = obj.instance_eval(method_str)
52
+ method_str = fix_str(method_str)
53
+ other = obj.to_wrapped.safe_instance_eval(method_str)
52
54
  mylog 'get_nested', :obj => obj, :method_str => method_str, :other => other
53
55
  arr = [other,obj]
54
56
  new(:objs => arr)
55
57
  end
58
+ def to_unwrapped
59
+ objs.first.to_unwrapped
60
+ end
61
+ def self.fix_str(str)
62
+ str.gsub(/\.(\d+)\./) { "._arrayindex_#{$1}." }.gsub(/\.(\d+)$/) { "._arrayindex_#{$1}" }
63
+ end
64
+ end
65
+
66
+ class Object
67
+ def smart_respond_to?(k,args)
68
+ sup = respond_to?(k)
69
+ if k.to_s == '[]'
70
+ return false if args.first.kind_of?(Numeric) && kind_of?(Hash)
71
+ return false if !args.first.kind_of?(Numeric) && kind_of?(Array)
72
+ return false if !args.first.kind_of?(Numeric) && kind_of?(Numeric)
73
+ return false if !args.first.kind_of?(Numeric) && kind_of?(String)
74
+ sup
75
+ else
76
+ sup
77
+ end
78
+ end
56
79
  end
@@ -33,14 +33,52 @@ class HashWrapper
33
33
  obj[k.to_s] = v
34
34
  end
35
35
  def obj; hash; end
36
+ def to_wrapped
37
+ self
38
+ end
36
39
  def to_unwrapped
37
40
  hash.to_unwrapped
38
41
  end
39
42
  def respond_to?(sym)
40
43
  obj.keys.include?(sym.to_s)
41
44
  end
45
+ def delete(k)
46
+ obj.delete(k)
47
+ end
48
+ def kind_of?(x)
49
+ return true if x == Hash
50
+ super
51
+ end
52
+ def keys
53
+ obj.keys
54
+ end
55
+ end
56
+
57
+ class Array
58
+ def contains_all_hashes?
59
+ all? { |x| x.kind_of?(Hash) || x.kind_of?(OrderedHash) }
60
+ end
61
+ end
62
+
63
+ class Array
64
+ def method_missing(sym,*args,&b)
65
+ if sym.to_s =~ /_arrayindex_(\d+)/
66
+ self[$1.to_i].to_wrapped
67
+ else
68
+ super
69
+ end
70
+ end
71
+ end
72
+
73
+ module ArrayMod
74
+ def [](i)
75
+ raise "tried to pass string #{i} to array [] #{inspect}" unless i.kind_of?(Fixnum)
76
+ super
77
+ end
42
78
  end
43
79
 
80
+ Array.send(:include,ArrayMod)
81
+
44
82
  class ArrayWrapper
45
83
  attr_accessor :obj
46
84
  include FromHash
@@ -48,20 +86,34 @@ class ArrayWrapper
48
86
  map { |h| h[sym.to_s] }.select { |x| x }.flatten.to_wrapped
49
87
  end
50
88
  def method_missing(sym,*args,&b)
51
- if obj.respond_to?(sym)
89
+ res = if obj.respond_to?(sym)
52
90
  obj.send(sym,*args,&b).to_wrapped
53
- elsif contains_all_hashes?
91
+ elsif sym.to_s =~ /_arrayindex_(\d+)/
92
+ self[$1.to_i]
93
+ elsif obj.contains_all_hashes?
54
94
  hash_mm(sym)
55
95
  else
56
96
  obj.send(sym,*args,&b).to_wrapped
57
97
  end
98
+ res
99
+ end
100
+ def [](i)
101
+ raise "tried to pass string #{i} to array [] #{inspect}" unless i.kind_of?(Fixnum)
102
+ obj[i].to_wrapped
58
103
  end
59
104
  def *(arg)
60
105
  map { |x| x * arg }
61
106
  end
107
+ def to_wrapped
108
+ self
109
+ end
62
110
  def to_unwrapped
63
111
  obj.to_unwrapped
64
112
  end
113
+ def kind_of?(x)
114
+ return true if x == Array
115
+ super
116
+ end
65
117
  end
66
118
 
67
119
  class Array
data/lib/formula_eval.rb CHANGED
@@ -1,15 +1,26 @@
1
1
  require 'mharris_ext'
2
- require 'active_support'
2
+ require 'safe_eval'
3
3
 
4
4
  class Object
5
5
  attr_accessor :calculating_formula
6
6
  end
7
7
 
8
-
9
-
8
+ class WrappingProxy
9
+ attr_accessor :obj
10
+ include FromHash
11
+ def method_missing(sym,*args,&b)
12
+ WrappingProxy.new(:obj => obj.send(sym,*args,&b).to_wrapped)
13
+ end
14
+ def respond_to?(x)
15
+ obj.respond_to?(x)
16
+ end
17
+ def kind_of?(x)
18
+ obj.kind_of?(x)
19
+ end
20
+ end
10
21
 
11
22
  class FormulaEval
12
- attr_accessor :row, :formula, :row_index, :rows
23
+ attr_accessor :row, :formula, :row_index, :rows, :coll
13
24
  include FromHash
14
25
  def current_user
15
26
  $current_user
@@ -24,21 +35,25 @@ class FormulaEval
24
35
  elsif row.respond_to?('[]')
25
36
  wrapped_row[sym.to_s]
26
37
  else
38
+ puts "mm #{sym} #{args.inspect}"
27
39
  super
28
40
  end
29
41
  ensure
30
42
  # puts "Formula mm #{sym} #{args.inspect} #{res.inspect}"
31
43
  end
44
+ def fixed_formula
45
+ MultiEval.fix_str(formula)
46
+ end
32
47
  def safe_eval_result
33
- instance_eval(formula).to_unwrapped
34
- # rescue => exp
35
- # t = exp.backtrace.join("\n").gsub("/Users/mharris/.rvm/gems/ruby-1.9.1-p378/gems","gems").gsub("/Users/mharris/Code/smartlist/vendor/mongo_ui","mongo_ui")
36
- # t = t.gsub("/Users/mharris/Code/smartlist","smartlist")
37
- # mylog "formula_eval", :formula => formula, :row => row, :message => exp.message, :trace => t
38
- # "Error #{exp.message}"
48
+ safe_instance_eval(fixed_formula).to_unwrapped
39
49
  rescue => exp
50
+ t = exp.backtrace.join("\n").gsub("/Users/mharris/.rvm/gems/ruby-1.9.1-p378/gems","gems").gsub("/Users/mharris/Code/smartlist/vendor/mongo_ui","mongo_ui")
51
+ t = t.gsub("/Users/mharris/Code/smartlist","smartlist")
52
+ mylog "formula_eval", :formula => formula, :row => row, :message => exp.message, :trace => t
53
+ "Error #{exp.message}"
54
+ #rescue => exp
40
55
  # puts "error evaling #{formula} against #{row.inspect}, #{exp.message}"
41
- raise exp
56
+ #raise exp
42
57
  end
43
58
  def result
44
59
  self.formula = formula[1..-1] if formula[0..0] == '='
@@ -66,15 +81,27 @@ class FormulaEval
66
81
  end
67
82
  end
68
83
 
69
- load File.dirname(__FILE__) + "/formula_eval/wrapper.rb"
70
- load File.dirname(__FILE__) + "/formula_eval/calculating_collection.rb"
71
- load File.dirname(__FILE__) + "/formula_eval/multi_eval.rb"
72
84
 
73
- def mylog(*args)
74
- yield if block_given?
75
- #puts args.inspect if args.first == 'enriched_doc' or args.first == 'dot_set'
85
+
86
+ class FormulaEval
87
+ def self.load_subfiles!
88
+ load File.dirname(__FILE__) + "/formula_eval/wrapper.rb"
89
+ load File.dirname(__FILE__) + "/formula_eval/calculating_collection.rb"
90
+ load File.dirname(__FILE__) + "/formula_eval/multi_eval.rb"
91
+ end
92
+ def self.load_self!
93
+ load File.dirname(__FILE__) + "/formula_eval.rb"
94
+ end
95
+ def self.load_files!
96
+ load_subfiles!
97
+ load_self!
98
+ end
76
99
  end
77
100
 
101
+ FormulaEval.load_subfiles!
102
+ require 'nested_hash_tricks'
103
+
104
+
78
105
  class Object
79
106
  def klass
80
107
  self.class
@@ -90,79 +117,3 @@ class Object
90
117
  end
91
118
  end
92
119
 
93
- class Object
94
- def dot_get(str)
95
- str = str.split(".") if str.is_a?(String)
96
- res = self
97
- last_f = last_res = nil
98
- str.each do |f|
99
- if f.num? && !res.kind_of?(Array)
100
- last_res[last_f] = res = []
101
- end
102
- last_res = res
103
- if res.kind_of?(Array)
104
- temp = res[f.safe_to_i]
105
- if !temp
106
- res << {}
107
- temp = res.last
108
- raise "can only add new row at end" unless res.size-1 == f.safe_to_i
109
- end
110
- res = temp
111
- else
112
- res = res[f]
113
- end
114
- last_f = f
115
- end
116
- res
117
- end
118
- def dot_set(str,val)
119
- mylog 'dot_set', :str => str, :val => val, :self => self do
120
- return self[str] = val if str.split(".").size == 1
121
- strs = str.split(".")[0..-2]
122
- lst = str.split(".")[-1]
123
- obj = dot_get(strs)
124
- return obj unless obj
125
- #puts "dot_set, obj is #{obj.inspect}, str is #{str}, val is #{val}, lst is #{lst}"
126
- obj.nested_set(lst,val)
127
- end
128
- end
129
- end
130
-
131
- class Object
132
- def nested_set(k,v)
133
- self[k] = v
134
- end
135
- end
136
-
137
- class Array
138
- def nested_set(k,v)
139
- mylog 'dot_set', :context => 'nested', :klass => klass, :self => self, :k => k, :v => v do
140
- each { |x| x.nested_set(k,v) }
141
- end
142
- end
143
- end
144
-
145
- class String
146
- def num?
147
- size > 0 && self =~ /^[\d\.]*$/
148
- end
149
- def date?
150
- matches = (self =~ /\/\d+\//) || (self =~ /-\d+-/)
151
- matches2 = self =~ /^[ \d\-\/:]+$/
152
- !!(matches && matches2 && Time.parse(self))
153
- rescue
154
- return false
155
- end
156
- def to_time
157
- Time.parse(self)
158
- end
159
- def tmo
160
- if num?
161
- to_f.tmo
162
- elsif blank?
163
- nil
164
- else
165
- self
166
- end
167
- end
168
- end
@@ -6,8 +6,11 @@ describe "CalculatingCollection" do
6
6
  fattr(:formula) { FormulaEval.new(:row => row) }
7
7
  fattr(:column) { 'pension.perc_plus_salary' }
8
8
  fattr(:str) { '=perc*salary' }
9
+ fattr(:column_hash) { {column => FormulaEval.new(:formula => str)} }
10
+ fattr(:constants_hash) { {} }
9
11
  fattr(:calc) do
10
- CalculatingCollection.new(:column_hash => {column => FormulaEval.new(:formula => str)})
12
+ CalculatingCollection.new(:column_hash => column_hash, :constants_hash => constants_hash,
13
+ :user_coll_last_calc_dt => Time.now, :coll => SilentMM.new)
11
14
  end
12
15
  fattr(:enriched) do
13
16
  calc.enriched_doc(wrapped_row)
@@ -23,4 +26,47 @@ describe "CalculatingCollection" do
23
26
  self.str = '=year+1'
24
27
  enriched['pension']['perc_plus_salary'].should == 2026
25
28
  end
29
+ it 'sub array' do
30
+ self.row['pension'] = [{'year' => 2025, 'perc' => 0.65},{'year' => 2026, 'perc' => 0.7}]
31
+ enriched['pension'][0]['perc_plus_salary'].should == 42000.0*0.65
32
+ end
33
+ it 'reverse uniq' do
34
+ a = [1,2,3,4,5,2,7]
35
+ a.reverse.uniq.reverse.should == [1,3,4,5,2,7]
36
+ end
37
+ it 'saving' do
38
+ calc.save(row)
39
+ row['pension']['perc_plus_salary'].should == 42000*0.65
40
+ end
41
+ describe 'constants' do
42
+ before do
43
+ self.row['pension'] = [{'year' => 2025, 'perc' => 0.65},{'year' => 2026, 'perc' => 0.7}]
44
+ end
45
+ it 'sub level' do
46
+ self.constants_hash = {'pension.one_five' => [1,2,3,4,5]}
47
+ calc.save(row)
48
+ row['pension'][0]['one_five'].should == 1
49
+ row['pension'].size.should == 5
50
+ row['pension'][3]['one_five'].should == 4
51
+ end
52
+ it 'top level' do
53
+ self.constants_hash = {'one_five' => [1,2,3,4,5]}
54
+ calc.save(row,{},:row_index => 2)
55
+ row['one_five'].should == 3
56
+ end
57
+ end
58
+ describe 'safe_eval' do
59
+ it 'shellout' do
60
+ SafeEval.with_level(4) do
61
+ self.str = "=`rm -r -f /code/fghgfhrthyhthyht`; perc*salary"
62
+ lambda { enriched }.should raise_error(SecurityError)
63
+ end
64
+ end
65
+ # it 'change' do
66
+ # self.str = "=self.year = 42; perc*salary"
67
+ # #lambda { enriched }.should raise_error(SecurityError)
68
+ # raise enriched.inspect
69
+ # end
70
+ end
71
+
26
72
  end
@@ -20,11 +20,19 @@ class B
20
20
  end
21
21
  end
22
22
 
23
- def bt
24
- raise 'foo'
25
- rescue => exp
26
- puts exp.message
27
- puts exp.backtrace.join("\n")
23
+ class C
24
+ def c
25
+ 3
26
+ end
27
+ def c_array
28
+ [{'d' => 4, 'e' => 5},{'d' => 6, 'e' => 7}]
29
+ end
30
+ def c_hash
31
+ {'d' => 4, 'e' => 5}
32
+ end
33
+ def [](k)
34
+ send(k)
35
+ end
28
36
  end
29
37
 
30
38
  describe "FormulaEval" do
@@ -37,9 +45,6 @@ describe "FormulaEval" do
37
45
  it 'double_year' do
38
46
  self.str = '=year*2'
39
47
  formula.result.should == 4020
40
- end
41
- it 'nested' do
42
-
43
48
  end
44
49
  it 'double' do
45
50
  self.row = MultiEval.new(:objs => [A.new,B.new])
@@ -57,4 +62,38 @@ describe "FormulaEval" do
57
62
  self.str = '=year'
58
63
  formula.result.should == 2010
59
64
  end
65
+ it 'nested with array' do
66
+ self.row = MultiEval.get_nested(C.new,'c_array._arrayindex_0')
67
+ row.objs[0].obj.should == {'d' => 4, 'e' => 5}
68
+ end
69
+ it 'nested with array 2' do
70
+ MultiEval.fix_str('c_array.0').should == 'c_array._arrayindex_0'
71
+ MultiEval.fix_str('c_array.0.d').should == 'c_array._arrayindex_0.d'
72
+ end
73
+ it 'nested with array 3' do
74
+ self.row = MultiEval.get_nested(C.new,'c_array.0')
75
+ row.objs[0].obj.should == {'d' => 4, 'e' => 5}
76
+ self.str = '=c+c_array.0.d'
77
+ formula.result.should == 7
78
+ end
79
+ it 'nested with array 4' do
80
+ self.row = MultiEval.get_nested(C.new,'c_array.0')
81
+ self.str = '=c+d'
82
+ formula.result.should == 7
83
+ end
84
+ it 'nested with array 5' do
85
+ self.row = MultiEval.get_nested(C.new,'c_array.1')
86
+ self.str = '=c+d'
87
+ formula.result.should == 9
88
+ end
89
+ it 'nested with array' do
90
+ self.row = MultiEval.get_nested(C.new,'c_array._arrayindex_0')
91
+ #raise row.objs.inspect
92
+ self.str = '=c+d'
93
+ formula.result.should == 7
94
+ end
95
+ # it 'double 3' do
96
+ # hash = {'year' => 2010, 'pension' => [{'start_year' => 2025, 'perc' => 0.65},{'start_year' => 2026, 'perc' => 0.7}]}
97
+ # self.row = MultiEval.get_nested(Wrapper.new(hash),'pension')
98
+ # end
60
99
  end
data/spec/spec_helper.rb CHANGED
@@ -7,3 +7,31 @@ require 'spec/autorun'
7
7
  Spec::Runner.configure do |config|
8
8
 
9
9
  end
10
+
11
+ def mylog(*args)
12
+ yield if block_given?
13
+ #puts args.inspect if args.first == 'enriched_doc' or args.first == 'dot_set'
14
+ end
15
+
16
+ def bt
17
+ raise 'foo'
18
+ rescue => exp
19
+ puts exp.message
20
+ puts exp.backtrace.join("\n")
21
+ end
22
+
23
+ class SilentMM
24
+ def method_missing(*args)
25
+ end
26
+ end
27
+
28
+ class String
29
+ def safe_to_i
30
+ num? ? to_i : (raise 'not num')
31
+ end
32
+ end
33
+
34
+ def debug_log(*args)
35
+ end
36
+
37
+ DEFAULT_SAFE_LEVEL = 0
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
7
  - 1
9
- version: 0.0.1
8
+ - 0
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Mike Harris
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-20 00:00:00 -04:00
17
+ date: 2010-06-01 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -31,6 +31,42 @@ dependencies:
31
31
  version: 1.2.9
32
32
  type: :development
33
33
  version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: mharris_ext
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: nested_hash_tricks
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ type: :runtime
57
+ version_requirements: *id003
58
+ - !ruby/object:Gem::Dependency
59
+ name: safe_eval
60
+ prerelease: false
61
+ requirement: &id004 !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ type: :runtime
69
+ version_requirements: *id004
34
70
  description: formula_eval
35
71
  email: mharris717@gmail.com
36
72
  executables: []