转: http://www.rorchina.net/?14/viewspace-1656.htm
================================================
《Web开发敏捷之道(第二版)》这本书已经买了好几个月了,但真正开始系统的学习还是这阵子的事儿。今天改写了书中一段不爽的例子,如下:
在介绍购物车的演示代码中(Page127),有如下例子:
------------------------------------------------------------------------------------------
<%= hidden_div_if(@cart.items.empty?, :id => "cart") %>
<%= render(:partial => "cart", :object => @cart) %>
</div>
module StoreHelper
def hidden_div_if(condition, attributes = {})
if condition
attributes["style"] = "display: none"
end
attrs = tag_options(attributes.stringify_keys)
<div #{attrs}>
end
end
------------------------------------------------------------------------------------------
模板代码的味道相当的不好,何出此言?明摆着半个</div>在外面放着,不恶心才怪,可见这些Rails专家写的代码并不能全信。
如果能像下面这样调用就爽了:
<% hidden_div_if(@cart.items.empty?, :id => "cart") do %>
<%= render(:partial => "cart", :object => @cart) %>
<% end %>
我们就按照这个目标重构,请看大屏幕:
module StoreHelper
def hidden_div_if(condition, attributes = {}, &block)
if condition
attributes["style"] = "display: none"
end
attrs = tag_options(attributes.stringify_keys)
content = capture(&block)
concat("<div #{attrs}>", block.binding)
concat(content, block.binding)
concat("</div>", block.binding)
end
end
搞定了!F5浏览一下吧。
================================================================
RoR相关API介绍:
concat(string, binding)
The preferred method of outputting text in your views is to use the <%= "text" %> eRuby
syntax. The regular puts and print methods do not operate as expected in an eRuby code
block. If you absolutely must output text within a code block, you can use the concat
method.
<% concat "hello", binding %>
is equivalent to using:
<%= "hello" %>
# File vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb, line 25
25: def concat(string, binding)
26: eval(ActionView::Base.erb_variable, binding) << string
27: end
capture(*args, &block)
Capture allows you to extract a part of the template into an instance variable. You can use
this instance variable anywhere in your templates and even in your layout.
Example of capture being used in a .rhtml page:
<% @greeting = capture do %>
Welcome To my shiny new web page!
<% end %>
Example of capture being used in a .rxml page:
@greeting = capture do
'Welcome To my shiny new web page!'
end
# File vendor/rails/actionpack/lib/action_view/helpers/capture_helper.rb, line 56
56: def capture(*args, &block)
57: # execute the block
58: begin
59: buffer = eval(ActionView::Base.erb_variable, block.binding)
60: rescue
61: buffer = nil
62: end
63:
64: if buffer.nil?
65: capture_block(*args, &block).to_s
66: else
67: capture_erb_with_buffer(buffer, *args, &block).to_s
68: end
69: end
参考:C:\ruby\lib\ruby\gems\1.8\gems\actionpack-1.13.5\lib\action_view\helpers\form_tag_helper.rb


