我有一个非常简单的 Ruby 问题。有没有办法重构这个:
<%= some_array.length if some_array.length > 1 %>
变成类似的东西
<%= some_array.length if self > 1 %>
'self'(例如)在哪里引用最初计算的值 - 即 some_array.length?
我有一个非常简单的 Ruby 问题。有没有办法重构这个:
<%= some_array.length if some_array.length > 1 %>
变成类似的东西
<%= some_array.length if self > 1 %>
'self'(例如)在哪里引用最初计算的值 - 即 some_array.length?
不,你不能这样做。该语句不会以您假设的方式从左到右进行评估。该if
语句首先被评估,因此没有“自我”要测试。正如您所说的,“初始计算值”首先由if
语句计算。
如果你不想计算 2 次,你可以这样做
<% len = some_array.length %>
<%= len if len > 1 %>
否则你可以创建辅助方法。最初的问题有点误导,因为 if 的左侧不会在右侧之前计算,所以即使您可以将“您的自我”作为计算值传递(您的伪代码):
people.destroy_all if self > 100
这将始终计算破坏以产生“你的自我”:D
我喜欢保持主模板简单,并将逻辑拉入助手中。erb 可以包含:
<%= display_length(some_array) %>
助手包含:
def display_length(array)
array.length if array.length > 1
end
当然,调整名称以最好地代表您的业务逻辑。
也许:
length if (length = some_array.length) > 1
有点深奥,但更短...
你能做的最好的事情或多或少是这样的:
t = some_array.length; t if t > 1
另外,请注意,有条件的插值 ERB 表达式(不带else
)将在一种情况和nil
另一种情况下返回值。ERB 实施将评估result.to_s
并产生“” #to_s
。nil
因此,它是一种可行的设计模式,但可能不容易被以后出现的所有代码阅读器所理解。
class Object
def block_scope
yield self
[] # Required for HAML and probably ERB as well
end
end
再培训局:
<% array.length.block_scope do |l| %>
<%= l if l > 1 %>
<% end %>
哈姆勒:
- array.length.block_scope do |l|
= l if l > 1
视觉上比简单的分配好一点
更新
同意添加block_scope
到Object
命名空间对于视图来说绝对是矫枉过正,更好的解决方案是创建一个助手:
def block_scope(*args)
yield *args
[] #?
end
- block_scope(array.length) do |l|
= l if l > 1