0

在几个 railscast 中,Ryan Bates 将这个自定义的“可排序”助手与几个助手方法(http://railscasts.com/episodes/228-sortable-table-columns)结合使用。我只会给你看我修改过的版本。

'sortable' helper 方法看起来像这样(我出于自己的目的对其进行了修改,但基本逻辑是相同的)

def sortable(column, params, title = nil)
  title ||= column.titleize
  direction = column == YearlyDerivative.sort_column(params) && YearlyDerivative.sort_direction(params) == "desc" ? "asc" : "desc"
  link_to title, params.merge(:sort => column, :direction => direction)
end

我对上面的这条线感到困惑和不知所措:direction = column == YearlyDerivative.sort_column(params) && YearlyDerivative.sort_direction(params) == "desc" ? "asc" : "desc".

即使我确实知道所有语法、代数(让我想到 div/mult-first、add/sub-second 规则等)规则需要遵循这一行,我仍然可能没有必要的 ruby​​ 知识(“真实性”运营商)充分了解这里发生了什么。我要的是一个演练。对于初学者来说,我的保险丝一开始就被烧断了direction = column == ...。但是后来当另一个相等运算符和三元运算符介入时,我失去了所有的理解。

如果您想知道, sort_column 和 sort_direction 是 YearlyDerivative 类方法(它们实际上并不一定存在,我只需要从不同的地方调用它们就可以了)

def self.sort_column(p)
  YearlyDerivative.column_names.include?(p[:sort]) ? p[:sort] : "revenue_usd_mil_derivative"
end

def self.sort_direction(p)
  %w[asc desc].include?(p[:direction]) ? p[:direction] : "asc"
end

单行( direction = column == YearlyDerivative.sort_column(params) && YearlyDerivative.sort_direction(params) == "desc" ? "asc" : "desc") 包含一个赋值、两个相等运算符、一个 && 运算符和一个三元运算符。当然,包括外部调用的方法,它使用了 3 个三元运算符,但我理解这一点没有问题。

谢谢你的耐心。我希望理解这一点能给我和其他 SO 读者/搜索者带来一些意想不到的编程洞察力。

4

4 回答 4

1

在我的选择中,这是通过将一些逻辑整合到一行中而变得聪明的尝试之一,这确实不应该这样做。真正的最终结果是它令人困惑,并且会导致更难维护代码,因为它会减慢维护者的速度,因为他们弄清楚它在做什么:

direction = column == YearlyDerivative.sort_column(params) && YearlyDerivative.sort_direction(params) == "desc" ? "asc" : "desc".

拆开它:

if (
  (column == YearlyDerivative.sort_column(params)) &&
  (YearlyDerivative.sort_direction(params) == "desc")
)
  direction = "asc" 
else
  direction = "desc"
end

在 Ruby 中,我们还可以在保持可读性和可理解性的同时进一步简化它:

direction = if (
              (column == YearlyDerivative.sort_column(params)) &&
              (YearlyDerivative.sort_direction(params) == "desc")
            )
              "asc" 
            else
              "desc"
            end

它甚至可以这样写,就 Ruby 而言实际上是单行代码,但它仍然比原始的单行代码更容易理解,因为使用括号将逻辑分成块:

direction = (
  (column == YearlyDerivative.sort_column(params)) &&
  (YearlyDerivative.sort_direction(params) == "desc")
) ? "asc" : "desc"
于 2013-03-10T04:19:39.823 回答
0

在这里,一步一步:

  1. 设置direction为以下语句的结果
  2. 是否column等于YearlyDerivative.sort_direction(params)
  3. 如果 (2) 为真,则返回该行的其余部分
  4. 如果YearlyDerivative.sort_direction(params) == "desc"为真,则返回"asc",否则"desc"

或者这个(大致)等效的代码:

if(column == YearlyDerivative.sort_direction(params))
  if(YearlyDerivative.sort_direction(params) == "desc")
    direction = "asc"
  else
    direction = "desc"
  end
else
  false
end
于 2013-03-10T03:50:49.750 回答
0

由于方法中封装了三元运算符的调用队列你理解起来没有问题,我建议你把单行拆开再装回去:

def func1
  column == YearlyDerivative.sort_column(params)
end
def func2 
  YearlyDerivative.sort_direction(params) == "desc" ? "asc" : "desc"
end
direction = func1 && func2

现在让我们把它组装回来:

#           ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓ func1 ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓    ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓ func2 ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓ 
direction = (column == YearlyDerivative.sort_column(params)) && (YearlyDerivative.sort_direction(params) == "desc" ? "asc" : "desc")

根据运算符优先级表,上面的大括号可以很容易地省略。

此外,现在您可以摆脱功能以纪念全单行:

direction = column == (YearlyDerivative.column_names.include?(p[:sort]) ? p[:sort] : "revenue_usd_mil_derivative") && %w[asc desc].include?(params[:direction]) ? params[:direction] : "asc") == "desc" ? "asc" : "desc"

希望有帮助。

于 2013-03-10T04:21:25.380 回答
0

我实际上已经将我的代码切换到以下

def sortable(column, params, title = nil)
  title ||= column.titleize
  if YearlyDerivative.test_column(params) && YearlyDerivative.sort_direction(params) == "asc"
    direction = "desc"
  else
    direction = "asc"
  end
  link_to title, params.merge(:sort => column, :direction => direction)
end

请注意 sort_column 方法已更改为 test_column 方法,我觉得这更合乎逻辑。

def self.test_column(p)
  YearlyDerivative.column_names.include?(p[:sort]) ? true : false
end

sort_column 方法仍然被 'sort' 类方法使用(如下)

def self.sort(params); p = params
  order(sort_column(p) + " " + sort_direction(p))
end

** 看起来原始可排序辅助方法中的 2 部分条件要求的第一部分是无用的。就 && 运算符而言,它返回 true。

def sort_column(p)
  ["a", "b", "c"].include?(p[:sort]) ? p[:sort] : "is it true or false?"
end
bad_params = {:sort => "d"}
x = true
if sort_column(bad_params) && x
  puts "hmm"
else; puts "it implied false"
end
#=> "hmm"

上面的 ruby​​ 特性测试使我创建了 test_column 方法。

于 2013-03-10T05:14:34.963 回答