我应该如何在ruby中重构这个条件代码?

时间:2016-12-18 22:09:05

标签: ruby refactoring

如何重构此功能?

  def split_description(first_n)
    description_lines = description.split "\n"
    line_num = description_lines.length
    if line_num > first_n
      @description_first = to_html(description_lines[0..first_n].join("\n"))
      @description_remain = to_html(description_lines[first_n + 1..line_num].join("\n"))
    elsif line_num > 1
      @description_first = to_html(description_lines[0..first_n].join("\n"))
      @description_remain = ''
    else
      @description_first = ''
      @description_remain = ''
    end
  end

我是Ruby的首发,遇到这个rubocup警告:Method has too many lines. [13/10]

以下是整个代码网址: https://github.com/RubyStarts3/YPBT-app/blob/master/views_objects/video_info_view.rb

4 个答案:

答案 0 :(得分:3)

<强>代码

def split_description(description, first_n)
  @description_first, @description_remain =
  case description.count("\n")
  when 0..first_n
    [description, '']
  else
    partition_description(description, first_n)
  end.map(&:to_html)
end

def partition_description(description, first_n)
  return ['', description] if first_n.zero?
  offset = 0
  description.each_line.with_index(1) do |s,i|
    offset += s.size
    return [description[0,offset], description[offset..-1]] if i == first_n
  end
end

我假设to_html('') #=> '',但如果情况并非如此,则修改很简单。

示例

这样我们就可以看到to_html的效果,让我们来定义它。

def to_html(description)
  description.upcase
end

description =<<_
It was the best of times
it was the worst of times
it was the age of wisdom
it was the age of fools
_

split_description(description, 0)
@description_first
  #=> "" 
@description_remain
  #=> "IT WAS THE BEST OF TIMES\n..WORST OF TIMES\n..AGE OF WISDOM\n..AGE OF FOOLS\n" 

split_description(description, 1)
@description_first
  #=> "IT WAS THE BEST OF TIMES\n" 
@description_remain
  #=> "IT WAS THE WORST OF TIMES\n..AGE OF WISDOM\n..AGE OF FOOLS\n" 

split_description(description, 2)
@description_first
  #=> "IT WAS THE BEST OF TIMES\nIT WAS THE WORST OF TIMES\n" 
@description_remain
  #=> "IT WAS THE AGE OF WISDOM\nIT WAS THE AGE OF FOOLS\n" 

split_description(description, 3)
@description_first
  #=> "IT WAS THE BEST OF TIMES\n..WORST OF TIMES\n..AGE OF WISDOM\n" 
@description_remain
  #=> "IT WAS THE AGE OF FOOLS\n" 

split_description(description, 4)
@description_first
  #=> "IT WAS THE BEST OF TIMES\n..WORST OF TIMES\n..AGE OF WISDOM\n..AGE OF FOOLS\n" 
@description_remain
  #=> "" 

<强>解释

首先,似乎description是一个包含字符串的局部变量。如果是这样,它必须是方法的参数(以及first_n)。

def split_description(description, first_n)

我们想要为两个实例变量赋值,所以让我们从编写

开始
  @description_first, @description_remain =

实际上有两个步骤:获取所需的字符串,然后使用to_html映射它们。所以让我们首先集中精力迈出第一步。

我们现在将调整字符串

中的行数
  case description.count("\n")

首先,让我们来处理字符串不包含换行符的情况

  when 0
    [description, '']

如果字符串为空,则为['', ''];否则它将包含没有换行符的单个字符串。

接下来,假设字符串中的换行符数介于1和first_n之间。在这种情况下,@description_first将是整个字符串,@description_remain将为空。

  when 1..first_n
      [description, '']

由于when 0when 1..first_n都返回相同的双元素数组,我们可以将它们组合在一起:

  when 0..first_n
    [description, '']

为了做到这一点,first_n小于换行符的数量。对于换行符数大于first_n的情况,我使用了另一种方法。

  else
    partition_description(description, first_n)

partition_description只是确定description换行符first_n的偏移量,然后相应地对字符串进行分区。

最后,我们需要结束case语句,映射用to_html返回的两个字符串的数组并结束方法

  end.map(&:to_html)
end

正如我之前提到的,我假设to_html('') #=> ''。在我看来,这是处理空字符串的最佳位置。

请注意,我直接处理了字符串,而不是将字符串拆分成行,操纵行然后重新加入它们。

答案 1 :(得分:1)

由于它在每种情况下都被使用或消隐,因此将实例变量初始化为空白。

  def split_description(first_n)
    description_lines = description.split "\n"
    line_num = description_lines.length

    @description_first = ''
    @description_remain = ''

    if line_num > first_n
      @description_first = to_html(description_lines[0..first_n].join("\n"))
      @description_remain = to_html(description_lines[first_n + 1..line_num].join("\n"))
    elsif line_num > 1
      @description_first = to_html(description_lines[0..first_n].join("\n"))
    end
  end

我还将description_lines[first_n + 1..line_num].join("\n")的逻辑移到to_html( whatever_that_is( lines, from, to) )之类的方法中。如果你重复同一个电话,那么它就不会那么糟糕了,这个名字将描述它正在做什么。

答案 2 :(得分:1)

如果first_n总是大于1,我想你可以修改Schwern的答案:

...

@description_first = to_html(description_lines[0..first_n].join("\n")) if line_num > 1

  if line_num > first_n
        @description_remain = to_html(description_lines[first_n + 1..line_num].join("\n"))
  end
end

答案 3 :(得分:1)

这应该有效:

def split_description(description, first_n = 0)
  lines = description.each_line
  @description_first  = to_html(lines.take(first_n).join)
  @description_remain = to_html(lines.drop(first_n).join)
end

takedrop取代了您的所有逻辑,因为正如@Cary Swoveland在评论中提到的那样:

  • 如果你花费太多,你最终得到完整的数组,没有错误信息
  • 如果你丢了太多,你会用一个空数组结束,没有错误信息

示例:

[1,2].take(99) #=> [1, 2]
[1,2].drop(99) #=> []

同样each_line输出一个字符串数组,换行符仍然存在。不需要splitchompjoin("\n")