Hi,
I have a question about eval and binding, with mod_ruby.
It is no problem to execute CGI program on command-line,
but an internal error happened when executing as mod_ruby script.
Here is the scripts.
viewloader.rb:
.--------------------
def output(filename, _binding=TOPLEVEL_BINDING)
s = nil
File.open(filename) do |file|
s = file.read
end
s.untaint
eval s, _binding
end
.--------------------
view.rb:
.--------------------
print “Hello #{username}!\n”
.--------------------
logic.rbx:
.--------------------
#!/usr/bin/ruby
require 'cgi’
cgi = CGI.new
print cgi.header
require 'viewloader’
username = 'Ruby’
output(‘view.rb’) # I prefer this rather than
# output(‘view.rb’, binding())
.--------------------
result(command-line): – No Problem.
.====================
$ ruby logic.rbx
(offline mode: enter name=value pairs on standard input)
Content-Type: text/html
Hello Ruby!
.====================
result(apache error_log): – INTERNAL ERROR!
.====================
[Thu May 1 11:41:59 2003] [error] mod_ruby: error in ruby
/home/httpd/html/sample/viewloader.rb:7:in eval': (eval):1: undefined local variable or method
username’ for #Object:0x40b35c90
(NameError)
from /home/httpd/html/sample/viewloader.rb:7:in output' from /home/httpd/html/sample/logic.rbx:9 from /usr/lib/ruby/1.6/apache/ruby-run.rb:63:in
load’
from /usr/lib/ruby/1.6/apache/ruby-run.rb:63:in `handler’
from ruby:0
.====================
I don’t know why the mod_ruby error happens.
Please give me an advice.
I can succeed if using output(‘view.rb’, binding)
instead of output(‘view.rb’) in logic.rbx,
but I want to use the former.
···
–
regards
kwatch
I think it’s because mod_ruby loads your code into an anonymous module, to
protect the top-level namespace which is shared by all the mod_ruby
applications running under the same interpreter. See
http://ruby-talk.org/65376
http://ruby-talk.org/56532
Regards,
Brian.
···
On Thu, May 01, 2003 at 12:59:22PM +0900, kwatch wrote:
I have a question about eval and binding, with mod_ruby.
It is no problem to execute CGI program on command-line,
but an internal error happened when executing as mod_ruby script.
Brian Candler B.Candler@pobox.com wrote in message news:20030501083010.GA41857@uk.tiscali.com…
I think it’s because mod_ruby loads your code into an anonymous module, to
protect the top-level namespace which is shared by all the mod_ruby
applications running under the same interpreter. See
http://ruby-talk.org/65376
http://ruby-talk.org/56532
I got. Thanks for a good advice.
I must use binding() in conclusion.
But how ERuby can do ERuby::import() ?
I think ERuby may calls eval in itself, but it has no need to
call binding().
view.rhtml
.--------------------
Hello <%= username %>!
.--------------------
logic.rbx
.--------------------
require ‘cgi’
cgi = CGI.new
print cgi.header
require ‘eruby’
username = ‘Ruby’
ERuby::import(‘view.rhtml’) # no binding(), but evaled with no error.
.--------------------
I have read ERuby source code (eruby_load() in eruby_lib.c),
but I could not get understand how ERuby do.
Would you teach me if you know it?
Maybe, getting a binding() of anonymous package?
regards,
kwatch
I don’t But I have just installed eruby now…
I’ve played with this a bit and have been unable to make the local variable
‘username’ available in viewloader.rb without passing a binding explicitly
as you did - having tried various combinations of instance_eval, passing in
‘self’ as a parameter etc.
The usual rule is that when you call a method, a new scope is started (so
local variables in the calling method are not visible in the called method).
I don’t understand how or why ERuby::import is able to see them when it
calls ‘eval’. The relevant function in eruby_lib.c looks like
static VALUE eruby_import(VALUE self, VALUE filename)
{
VALUE compiler, file, code;
compiler = eruby_compiler_new();
file = rb_file_open(STR2CSTR(filename), "r");
code = eruby_compiler_compile_file(compiler, file);
rb_funcall(ruby_top_self, rb_intern("eval"), 3, code, Qnil, filename);
return Qnil;
}
And the closest I can get to simulate that is:
···
On Fri, May 02, 2003 at 07:43:42AM +0900, kwatch wrote:
view.rhtml
.--------------------
Hello <%= username %>!
.--------------------
logic.rbx
.--------------------
require ‘cgi’
cgi = CGI.new
print cgi.header
require ‘eruby’
username = ‘Ruby’
ERuby::import(‘view.rhtml’) # no binding(), but evaled with no error.
.--------------------
I have read ERuby source code (eruby_load() in eruby_lib.c),
but I could not get understand how ERuby do.
Would you teach me if you know it?
TOP_SELF = self
module Foo
def Foo.output(code)
TOP_SELF.send( :eval, code )
end
end
username=“test”
Foo.output(“puts username”)
but this doesn’t work Anybody else got any better ideas, or an
explanation of why ERuby doesn’t need you to pass in an explicit ‘binding’?
Thanks,
Brian.