使用|| in case在Rails中切换方法

时间:2016-03-02 09:55:30

标签: ruby-on-rails ruby switch-statement

跟进这个问题的问题

Using || in Case switch in Rails

我的问题是在方法中包装when时应该做些什么来使代码更具可读性。像你写的那样直接返回它对我不起作用?

示例:

case @page_title
when "Log in", "Forgot Your Password", "Create a New Password" then #...

我想:

case @page_title
when unprotected then #...

根据以下答案我的解决方案是(使用if和elsif代替)

之前的代码(切换):

case stats_category.unit
when StatsCategory::UNITS::SAME_AS_NAME_INTEGER, StatsCategory::UNITS::SECONDS
  if !is_integer
    @error = true
    @message = ""
  else
    write_attribute(:data,value)
  end
when StatsCategory::UNITS::KILOMETERS, StatsCategory::UNITS::SAME_AS_NAME_DECIMAL
  if !is_float
    @error = true
    @message = ""
  else
    write_attribute(:data,value)
  end
when StatsCategory::UNITS::HH_MM_SS
  if !is_HH_MM_SS
    @error = true
    @message = ""
  else
    write_attribute(:data,value.split(":").sum)
  end
end 

refac之后的代码(if,elsif):

category_unit = stats_category.unit
    if integer_unit(category_unit)
      if !is_integer
        @error = true
        @message = ""
      else
        write_attribute(:data,value)
      end
    elsif float_unit(category_unit)
      if !is_float
        @error = true
        @message = ""
      else
        write_attribute(:data,value)
      end
    elsif time_format_HH_MM_SS(category_unit)
      if !is_HH_MM_SS
        @error = true
        @message = ""
      else
        write_attribute(:data,value.split(":").sum)
      end
    else
    end

def integer_unit(unit)
    unit === StatsCategory::UNITS::SAME_AS_NAME_INTEGER || unit === StatsCategory::UNITS::SECONDS
  end

  def float_unit(unit)
    unit === StatsCategory::UNITS::KILOMETERS  || unit === StatsCategory::UNITS::SAME_AS_NAME_DECIMAL
  end

  def time_format_HH_MM_SS(unit)
    unit === StatsCategory::UNITS::HH_MM_SS
  end

找到答案。我的代码根据Sergio Tulentsev提供的解决方案

开关:

case stats_category.unit
      when *integer_unit
        if !is_integer
          @error = true
          @message = ""
        else
          write_attribute(:data,value)
        end
      when *float_unit
        if !is_float
          @error = true
          @message = ""
        else
          write_attribute(:data,value)
        end
      when *time_format_HH_MM_SS
        if !is_HH_MM_SS
          @error = true
          @message = ""
        else
          write_attribute(:data,value.split(":").sum)
        end
      end

方法:

def integer_unit
    [StatsCategory::UNITS::SAME_AS_NAME_INTEGER, StatsCategory::UNITS::SECONDS]
  end

  def float_unit
    [StatsCategory::UNITS::KILOMETERS, StatsCategory::UNITS::SAME_AS_NAME_DECIMAL]
  end

  def time_format_HH_MM_SS
    [StatsCategory::UNITS::HH_MM_SS]
  end

2 个答案:

答案 0 :(得分:2)

最简单的方法是使用ifelsif代替case

case在幕后使用===方法,因此您可以定义一个函数,该函数返回一个以您想要的方式响应===的对象。请参阅this article以了解相关信息。

示例:

def unprotected
  o = Object.new
  class << o
    def ===(s)
      s == 'a' || s == 'b'
    end
  end
  o
end

def test(page_title)
  result =
    case page_title
    when unprotected then 'match'
    else 'no match'
    end
  puts "#{page_title} => #{result}"
end

test 'a' # => match
test 'b' # => match
test 'c' # => no match

答案 1 :(得分:2)

You totally can use methods here. Have those methods return arrays [of possible options], which you will then splat.

def unprotected
  ["Log in", "Forgot Your Password", "Create a New Password"]
end

def check(page)
  case page
  when *unprotected then 'unprotected'
  else 'protected'
  end
end

check('Log in') # => "unprotected"
check('Buy') # => "protected"