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元编程