There's a problem. Proc objects can't be Marshalled which means they can't easily be stored.
I wrote a small method to build such a Dynamic proc first:
-
def procbuilder(cmd,*r)
-
argary = []
-
r.each_index do |i|
-
argary.push "arg_#{i}"
-
end
-
argstr = "|#{argary.join(',')}|"
-
p = %q(Proc.new {) + argstr + ' ' + cmd + '}'
-
eval p
-
end
To use it:
-
class Foo
-
attr_accessor :foo
-
def initalize
-
end
-
end
-
-
m = Foo.new
-
m.foo = 10
-
-
# First parameter is the command to perform. arg_? is predictable
-
# Following parameters are enumerated as arg_0, arg_1, arg_2
-
p = procbuilder('arg_0.foo = arg_0.foo * arg_1',m,1.05)
And for output:
-
puts p.call(m,1.05)
-
puts m.foo
Result of the call is 10.5 and the instance on the object is changed too.
This is kind of cool but not much use unless there's a way to store it. Here's some Rails schema.rb:
-
create_table "dyna_procs", :force => true do |t|
-
t.column "name", :string, :null => false
-
t.column "procsrc", :text
-
end
In the DynaProc model:
-
attr_reader :dproc
-
def after_initialize
-
procbuilder(self.procsrc) unless self.procsrc.nil?
-
end
-
-
private
-
def procbuilder(cmd)
-
@dproc = eval cmd
-
end
Then after the DynaProc is loaded the dproc is a Proc object. Whee.
How the DynaProc object is created (and stored) is irrelevant. It could be from an custom form where people drag and drop predefined elements or it could be a scaffolded web form. White list everything and validate everything. Next trick is to get it to automatically sandbox itself...

