首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

下手写rails(二)Rails_Ruby_ERB使用_模板_定制

2012-09-19 
动手写rails(二)Rails_Ruby_ERB使用_模板_定制动手写rails(二)Rails_Ruby_ERB使用_模板_定制?一。基础:基本

动手写rails(二)Rails_Ruby_ERB使用_模板_定制

动手写rails(二)Rails_Ruby_ERB使用_模板_定制

?

一。基础:基本知识

?

先看例子代码:

例子1:

require "erb"#例子1:erb = ERB.new("I am <%= 'Fantaxy' %>")puts "例子1:"puts erb.resultputs erb.src

?

输出:

例子1:

I am Fantaxy

_erbout = ''; _erbout.concat "I am "; _erbout.concat(( 'Fantaxy' ).to_s); _erbout

?

例子2:

#例子2:a = 123erb = ERB.new("it is <%=a %>")puts "例子2:"puts erb.result(binding)puts erb.src

输出:?

例子2:

it is 123

_erbout = ''; _erbout.concat "it is "; _erbout.concat((a ).to_s); _erbout

?

?

例子3:

erb_str = %q*  <%  x = "_aaa_"  1.upto(5) do |i|    x << "_#{i}_"  end  %>  <%= x %>*erb = ERB.new(erb_str)puts erb.result(binding)puts erb.src

输出:

?


??

? _aaa__1__2__3__4__5_

_erbout = ''; _erbout.concat "\n ?"

;?

? x = "_aaa_"

? 1.upto(5) do |i|

? ? x << "_#{i}_"

? end

? ; _erbout.concat "\n ?"

; _erbout.concat(( x ).to_s); _erbout.concat "\n"

; _erbout

?

?

小结:

#1 如果不是用绑定的变量,则不许要binding参数,否则需要把环境传进来

#2?ERB中可以使用<%= 1111 %> 和 <% 控制语句 %>, 这一点和jsp是如如出一辙的

#3 ERB的src命令可以输出可以run的ruby代码

#4 在rvm中运行输出的src代码 等价于 调用result方法 等价于在rvm中运行 eval(erb.src)

_erbout = ''; _erbout.concat "\n  ";   x = "_aaa_"  1.upto(5) do |i|    x << "_#{i}_"  end  ; _erbout.concat "\n  "; _erbout.concat(( x ).to_s); _erbout.concat "\n"; _erbout

输出:

?


??

? _aaa__1__2__3__4__5_

puts eval(erb.src)?

输出同上。

?

二。进阶:输出新起一行设置,安全设置,返回值设置,及灵活使用

?

ERB.new(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')

#1 安全级别

#2?新起一行设置

ERB默认会把%>结尾的行单独成行;

If?trim_mode?is passed a String containing one or more of the following modifiers,?ERB?will adjust its code generation as listed:

%  enables Ruby code processing for lines beginning with %<> omit newline for lines starting with <% and ending in %>>  omit newline for lines ending in %>

上面的输出部分,会看见前面有空行,这个就是输出的准确内容,空行原因就是这里说的。

?

#3 返回值设置

eoutvar?can be used to set the name of the variable?ERB?will build up its output in. This is useful when you need to run multiple?ERB?templates through the same binding and/or when you want to control where output ends up. Pass the name of the variable to be used inside a String.

例子:

require "erb"a = "Fantaxy"@output_buffer = "I am "erb = ERB.new("<% @output_buffer ||= '';%> Yes!  <%= @output_buffer << a %>", 1, "@output_buffer")puts erb.result(binding)a = "025025"puts erb.result(binding)puts @output_buffer

输出(请选中查看):

?

?Yes! ?I am Fantaxy

?Yes! ?I am Fantaxy025025

I am Fantaxy025025

?

这里有个问题,@output_buffer在模板中共用了。

因为变量共用导致了模板使用没有了独立性,一般不会使用共用变量的方式。

但如果不共用一个变量,erb每次都会重新对输出结果保存的变量进行赋值。

看这个例子:

require "erb"user_name = "Fantaxy"@output_buffer = ""puts "@output_buffer = #{@output_buffer}"erb = ERB.new("I am <%= user_name %>", 1, "<>", "@output_buffer")puts "erb_result = #{erb.result(binding)}"puts "@output_buffer = #{@output_buffer}"user_name = "June"puts "erb_result = #{erb.result(binding)}"puts "@output_buffer = #{@output_buffer}"

输出:

@output_buffer =?

erb_result = I am Fantaxy

@output_buffer = I am Fantaxy

erb_result = I am June

@output_buffer = I am June

?

从结果可以验证,@output_buffer的被重新赋值了。

为什么?

从本质上来说,erb的执行就是生成src后用rvm执行的。

每次调用src方法,都会重新使用输出变量并赋值为空字符串(''),请看前面几个例子中src生成的代码:

_erbout = '';

?

怎么解决这个问题:

折中的办法是保持erb模板文件的独立性,用逻辑来达到输出结果的关联。

看例子的改进版本:

require "erb"user_name = "Fantaxy"@output_buffer = ""puts "@output_buffer = #{@output_buffer}"erb = ERB.new("I am <%= user_name %>", 1, "<>", "@output_buffer")puts "erb_result = #{erb.result(binding)}"puts "@output_buffer = #{@output_buffer}"old_output_buffer = @output_buffer #先保存下来user_name = "June"puts "erb_result = #{erb.result(binding)}" #@output_buffer被覆盖了puts "@output_buffer = #{@output_buffer}"@output_buffer = "#{old_output_buffer} AND #{@output_buffer}"puts "@output_buffer = #{@output_buffer}"

输出结果:

@output_buffer =?

erb_result = I am Fantaxy

@output_buffer = I am Fantaxy

erb_result = I am June

@output_buffer = I am June

@output_buffer = I am Fantaxy AND I am June

?

这样就使得view的erb模板成为了独立,想怎么使用(比如内容前置,后置等),何时使用,交给了控制端灵活使用。

?

上面的做法可以解决view模板内容前置,后置的问题,但是如果想把一个view模板的内容插入另一个erb模板的中间,该怎么办呢?

需求简写条件:

erbA的内容是:

This is head

body content xxx

body(将会有内容插入此处)

body content yyy

This is foot

erbB的内容是:

I am Fantaxy

需求简写问题:

如何可以用erb渲染后,把erbB的内容插入erbA中间bodyXXX的位置(别用replace哈)

?

解决方法:yield

?

require "erb"#mocking@output_buffer = ""def test_erb_out_mocking_layout  erbA_str = <<-ERB    <%="This is head"%>    <%="body content xxx"%>    <% yield %>    <%="body content yyy"%>    <%="This is foot"%>  ERB  erbA = ERB.new(erbA_str, 1, '<>', "@output_buffer")  erbA.result(binding)end#runtest_erb_out_mocking_layout do  @old_output_buffer = @output_buffer  erbB = ERB.new("I am Fantaxy!", 1, '<>', "@output_buffer")  erbB.result(binding)  @output_buffer = "#{@old_output_buffer}#{@output_buffer}"end#testingputs @output_buffer?

输出:

?

? ? This is head

? ? body content xxx

? ? I am Fantaxy!

? ? body content yyy

? ? This is foot

这样rails的layout问题如何写的核心问题也就解决了。

再强调一下核心内容(对么?):

erb模板run(result)的过程本质就是转化成ruby语句后在rvm中运行。

上面的yield如何使用,只需要把erb的src输出来看看就知道了,这也是为什么这个例子包装入了一个方法内,其他的例子可以直接写代码了。(自己试试看吧,不贴上来了)

?

三。高级:erb的其他内容

?

1)erb中的ruby代码空白换行问题

erb中的ruby代码嵌入了<% ruby代码 %>

但是默认会认为其前后的内容也是输出result的结果。但很多时候不许要这个,比如html代码中的这些ruby逻辑控制,仅仅想让他成为控制,而不影响生成的html格式。

方法:上面已经有了,可以设置new中的3ed参数,以及解释:

%  enables Ruby code processing for lines beginning with %<> omit newline for lines starting with <% and ending in %>>  omit newline for lines ending in %>

?

但是rails中的 -%>怎么会其作用呢?

原来有个hack没有在文档中写出来:3ed参数传递'-'则打开了 <%- ?和 ?-%>标签

?

2)erb中可以定义方法和类等,作用如同freemarker中的macro或者c中的宏吧

A:定义Class:

<%# file: example.html.erb %><%= "arg1 = #{@arg1}" %><%= "arg2 = #{@arg2}" %>
class MyClass_1  def initialize(arg1, arg2)    @arg1 = arg1;  @arg2 = arg2  endendfilename = 'example.html.erb'  # @arg1 and @arg2 are used in example.html.erberb = ERB.new(File.read(filename))erb.filename = filenameMyClass_1 = erb.def_class(MyClass_1, 'render()')print MyClass_1.new('foo', 123).render()

?输出:

?

(注:空行)

arg1 = foo

arg2 = 123

?

?

B:定义方法

<%# example.rhtml %><%= "arg1 = #{arg1}" %><%= "arg2 = #{arg2}" %>
class MyClass; endfilename = 'example.rhtml'   # 'arg1' and 'arg2' are used in example.rhtmlerb = ERB.new(File.read(filename))erb.def_method(MyClass, 'render(arg1, arg2)', filename)print MyClass.new.render('foo', 123)

输出:同上

?

C:定义Module

?

filename = 'example.rhtml'   # 'arg1' and 'arg2' are used in example.rhtmlerb = ERB.new(File.read(filename))erb.filename = filenameMyModule = erb.def_module('render(arg1, arg2)')class MyClass  include MyModule  def test_render(arg1, arg2)    puts render(arg1, arg2)  endendMyClass.new.test_render("Lee", "June")

输出:

?

?

arg1 = Lee

arg2 = June

?

结束:

rails中使用的主要模板解析用的是ERB,避免不了很多的地方都出现了ERB的使用方法和技巧。

可以说,ERB的环境和使用方法,影响了整个MVC框架的VC层的设计。

?

?

参考:

官方api介绍比较详细的解释,erb

http://ruby-doc.org/stdlib-1.9.3/

换行问题和ERB标签的识别和扩展:

http://cheat.errtheblog.com/s/erb/

http://stackoverflow.com/questions/9208728/embedded-ruby-erb-tags

http://stackoverflow.com/questions/3311589/how-to-extend-ruby-erb-for-handling-tags-as-well

ERB的一个tutorial step by step:

http://www.stuartellis.eu/articles/erb/

讨论erb和rails以及mvc的几个帖子:

http://www.iteye.com/topic/72525#268222

http://www.iteye.com/topic/84116

?

?

? ? ? ? ? ? ||

? ? ? ? ? ?| ?|

? ? ? ? ? | ? ?|

====结束====

=== ? ? ? ? ? ===

== ? ? ? ? ? ? ? ?==

= ? ? ? ? ? ? ? ? ? ? =

| ? ? ? ? ? ? ? ? ? ? ? |

?

?

?

?

热点排行