formula_eval 0.0.1 → 0.1.0

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