2

我有一个非常简单的 Ruby 问题。有没有办法重构这个:

<%= some_array.length if some_array.length > 1 %>

变成类似的东西

<%= some_array.length if self > 1 %>

'self'(例如)在哪里引用最初计算的值 - 即 some_array.length?

4

7 回答 7

5

不,你不能这样做。该语句不会以您假设的方式从左到右进行评估。该if语句首先被评估,因此没有“自我”要测试。正如您所说的,“初始计算值”首先if语句计算。

于 2012-04-18T15:24:56.807 回答
1

如果你不想计算 2 次,你可以这样做

<% len = some_array.length %>
<%= len if len > 1 %>

否则你可以创建辅助方法。最初的问题有点误导,因为 if 的左侧不会在右侧之前计算,所以即使您可以将“您的自我”作为计算值传递(您的伪代码):

people.destroy_all if self > 100

这将始终计算破坏以产生“你的自我”:D

于 2012-04-18T15:30:47.570 回答
1

我喜欢保持主模板简单,并将逻辑拉入助手中。erb 可以包含:

<%= display_length(some_array) %>

助手包含:

def display_length(array)
  array.length if array.length > 1
end

当然,调整名称以最好地代表您的业务逻辑。

于 2012-04-18T15:57:07.077 回答
0

A. 你可以这样做

<%= l = some_array.length if l > 1 %>

B. 你可以使用Presenter 模式

于 2012-04-18T15:37:06.440 回答
0

也许:

length if (length = some_array.length) > 1

有点深奥,但更短...

于 2012-04-18T15:52:34.050 回答
0

你能做的最好的事情或多或少是这样的:

t = some_array.length; t if t > 1 

另外,请注意,有条件的插值 ERB 表达式(不带else)将在一种情况和nil另一种情况下返回值。ERB 实施将评估result.to_s并产生“” #to_snil因此,它是一种可行的设计模式,但可能不容易被以后出现的所有代码阅读器所理解。

于 2012-04-18T16:57:56.920 回答
-2
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_scopeObject命名空间对于视图来说绝对是矫枉过正,更好的解决方案是创建一个助手:

def block_scope(*args)
  yield *args
  [] #?
end

- block_scope(array.length) do |l|
  = l if l > 1
于 2012-04-18T16:16:24.337 回答