rails中的 erb代码执行原理
在rails erb文件中嵌入ruby代码,举个例子:
@a = 1
<div><%= @a %></div>rails输出的是:<div>1</div>
rails实现是:ERB.new("<div><%= @a %></div>").result
查看erb.rb源代码:
def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
@safe_level = safe_level
compiler = make_compiler(trim_mode)
set_eoutvar(compiler, eoutvar)
@src, @encoding, @frozen_string = *compiler.compile(str)
@filename = nil
@lineno = 0
end
def result(b=new_toplevel)
if @safe_level
proc {
$SAFE = @safe_level
eval(@src, b, (@filename || '(erb)'), @lineno)
}.call
else
eval(@src, b, (@filename || '(erb)'), @lineno)
end
end首先初始化ERB,然后result方法里调用eval,取变量的值相当于:eval("@a")
都是用eval("你的ruby代码"),执行并返回
那么<%%>呢?
erb.rb中通过字符串匹配来识别ruby代码,代码如下:
ERB_STAG = %w(<%= <%# <%)
def is_erb_stag?(s)
ERB_STAG.member?(s)
end
def compile_stag(stag, out, scanner)
case stag
when PercentLine
add_put_cmd(out, content) if content.size > 0
self.content = +''
out.push(stag.to_s)
out.cr
when :cr
out.cr
when '<%', '<%=', '<%#'
scanner.stag = stag
add_put_cmd(out, content) if content.size > 0
self.content = +''
when "\n"
content << "\n"
add_put_cmd(out, content)
self.content = +''
when '<%%'
content << '<%'
else
content << stag
end
end因为要解析erb,erb中的代码传到ruby中都是字符串,ERB底层非常灵性的使用eval解析字符串,运行ruby代码
更多操作可以看ruby元编程