如何减少 Ruby 代码的 nex 行?

How do I reduce the nex lines of Ruby code?

    def route_action(action)
    case action
    when 1 then @meals_controller.add
    when 2 then @meals_controller.list
    when 3 then @meals_controller.edit
    when 4 then @meals_controller.delete
    when 5 then @customers_controller.add
    when 6 then @customers_controller.list
    when 7 then @customers_controller.edit
    when 8 then @customers_controller.delete
    when 0 then stop
    else
      puts "Please press 1, 2, 3, 4, 5, 6, 7, 8 or 0"
    end
  end

所以我想减少这种情况,有没有其他实现方法?

一种可能性是根据用作索引的 action 输入发送一组消息名称,并通过除以 5 来确定发送到哪个控制器.从 14 的输入将产生 0,而 58 将产生 1.

def route_action
  actions = [:add, :list, :edit, :delete]

  case action
    when 1..8 
      controller = action / 5 < 1 ? @meals_controller : @customers_controller
      msg = actions[(action - 1) % 4]
      controller.send(msg)
    when 0 
      stop
    else
      puts "Please press 1, 2, 3, 4, 5, 6, 7, 8 or 0"
  end
end

怎么样:

CASES = [@meals_controller, @customers_controller].product([:add, :list, :edit, :delete])

def route_action(action)
  if action > 0
    selected = CASES[action-1] # something like [:@meals_controller, :add]
    if selected
      selected.first.send(*selected.last)
    else
      puts "action number too large"
    end
  elsif action == 0
    stop
  else # Do we have to catch this?
    puts "action number negative" # programming error?
  end
end

  

注意,这只是关于如何使用一点 Ruby meta-programming 来摆脱必须声明一个充满案例业务逻辑的长方法的纠结的一般建议。它不会完全适合并且需要额外的工作来完成,例如,“退出”逻辑。

还有。我将重申在对 post 的直接回答之一中所说的话。您的 case 解决方案非常明确。这是很好的代码,我们不应该仅仅为了遵守 all-mighty 样式表指南中的 all-mighty 神灵而跳入更混乱的事情。仅仅因为一个方法少于 10 行,它并不会自动使它比 11(或......地狱 40)行更好。

现在...

这里有一个 meta-programming 建议...

您可以在常量上定义一个散列来保存业务逻辑所需的变量:

ROUTES = [
  { action: :add,  controller: :meals, description: "Add a meal" },
  { action: :list, controller: :meals, description: "List all meals" },
  { action: :add,  controller: :customers, description: "Add a customers" },
  { action: :list, controller: :customers, description: "List all customers" },
]

然后您可以创建一个方法,使用哈希信息将用户分派到正确的控制器操作:

def dispatch(action_index)
  route_action     = ROUTES[action_index][:action]
  route_controller = ROUTES[action_index][:controller]
  instance_variable_get("@#{route_controller}_controller").send(route_action)
end

使用散列迭代它以显示路线描述非常容易:

def display_options
  ROUTES.each_with_index do |route, index|
    puts "#{index + 1}. #{route[:description]}"
  end
end

您可以在代码中的某个时刻使用 dispatch(gets.chomp.to_i - 1) 将用户分派到相关的控制器操作。

散列的妙处在于,您始终可以通过添加一行来为其添加更多路由。