Каков эффективный способ рефакторинга тяжелого оператора if в Ruby on Rails?

Каков эффективный способ рефакторинга сложного оператора if?

Все предложения приветствуются...

<% if @user.plan_id == 1 %>
      <span class="label label-info">Plan1</span>
  <% elsif @user.plan_id == 2 %>
      <span class="label label-warning">Plan2</span>
  <% elsif @user.plan_id == 3 %>
      <span class="label label-info">Plan3</span>
  <% elsif @user.plan_id == 4 %>
      <span class="label label-warning">Plan4</span>
  <% elsif @user.plan_id == 5 %>
      <span class="label label-info">Plan5</span>
  <% elsif @user.plan_id == 6 %>
      <span class="label label-warning">Plan6</span>
  <% elsif @user.plan_id == 7 %>
      <span class="label label-info">Plan7</span>   
  <% elsif @user.plan_id == 8 %>
      <span class="label label-warning">Plan8</span>
<% end %>

person Nathaniel Rand    schedule 23.08.2016    source источник
comment
используйте операторы case.   -  person Arun Kumar Mohan    schedule 23.08.2016
comment
Возможный дубликат stackoverflow.com/questions/35275608/   -  person Gerard Roche    schedule 23.08.2016
comment
Попробуйте выполнить поиск в stackoverflow stackoverflow.com/   -  person Gerard Roche    schedule 23.08.2016


Ответы (5)


Это задание для вспомогательного модуля, что-то вроде этого:

module UserPlanHelper
  PLANS = {
    1 => [ "info", "Plan1" ],
    2 => [ "warning", "Plan2" ],
    3 => [ "info", "Plan3" ],
    4 => [ "warning", "Plan4" ],
    5 => [ "info", "Plan5" ],
    6 => [ "warning", "Plan6" ],
    7 => [ "info", "Plan7" ],
    8 => [ "warning", "Plan8" ]
  }

  def plan_details(plan_id)
    yield(PLANS[plan_id])
  end
end

При использовании в вашем контроллере это упрощает ваш код до чего-то вроде:

<%= plan_details(@user.plan_id) do |label_class, label| %>
  <span class="label label-<%= label_class %>"><%= label %></span>
<%- end %>
person tadman    schedule 23.08.2016
comment
Небольшой вопрос: какова цель/преимущество добавления метода yield к методу plan_details? - person Utsav Kesharwani; 23.08.2016
comment
@UtsavKesharwani Это означает, что вы можете структурировать его как plan_details(...) do с блоком внутри, вместо того, чтобы создавать локальные переменные. - person tadman; 23.08.2016
comment
yield кажется странным образом недостаточно используемым за пределами кода уровня фреймворка в Ruby. Или, может быть, это просто код, на который я закончил смотреть. - person mu is too short; 23.08.2016
comment
@muistooshort Я использую его все время, но мне больше нравится квазифункциональное программирование, которое вы можете с ним делать. - person tadman; 23.08.2016
comment
То же самое. И множество лямбда-выражений, чтобы мои цепочки Enumerable было легче читать. Я даже был известен тем, что писал свои собственные классы, а не полагался на беспорядок вложенных хэшей и массивов, которые всем нравятся :) - person mu is too short; 23.08.2016

Ссылается ли plan_id на модель Plan? Если нет, я бы предложил создать его с атрибутом label и флагом elite. Тогда ваше утверждение будет таким:

<span class="label label-<%= @user.plan.elite ? 'warning' : 'info' %>}">
  <%= @user.plan.label %>
</span>
person Robert Nubel    schedule 23.08.2016

Вы можете использовать case

<% case @user.plan_id %>
<% when 1 %>
    <span class="label label-info">CONTRIBUTOR</span>
<% when 2 %>
    <span class="label label-warning">ELITE CONTRIBUTOR</span>
<% when 3 %>
     <span class="label label-info">TECHNICIAN</span>
<% when 4 %>
     <span class="label label-warning">ELITE TECHNICIAN</span>
<% when 5 %>
     <span class="label label-info">CENTER</span>
<% when 6 %>
     <span class="label label-warning">ELITE CENTER</span>
<% when 7 %>
     <span class="label label-info">AFFAIR</span>   
<% when 8 %>
      <span class="label label-warning">ELITE AFFAIR</span>
<% end %>
person Mike    schedule 23.08.2016

Определите вспомогательный метод:

def plan_hash
  {
    1 => { :klass => "label-info",    :description => "Plan1" },
    2 => { :klass => "label-warning", :description => "Plan2" },
    3 => { :klass => "label-info",    :description => "Plan3" },
    4 => { :klass => "label-warning", :description => "Plan4" },
    5 => { :klass => "label-info",    :description => "Plan5" },
    6 => { :klass => "label-warning", :description => "Plan6" },
    7 => { :klass => "label-info",    :description => "Plan7" },
    8 => { :klass => "label-warning", :description => "Plan8" }
  }
end

Тогда, на ваш взгляд:

<span class="label <%= plan_hash[@user.plan_id][:klass] %>"><%= plan_hash[@user.plan_id][:description] %></span>
person Utsav Kesharwani    schedule 23.08.2016
comment
Если есть какая-то корреляция между klass и description, я могу реорганизовать вспомогательный метод. Поскольку пользователь ничего не указал как таковой, я сделал это простым и понятным. :) - person Utsav Kesharwani; 23.08.2016

<span class="label label-<%= @user.add_warning? ? 'warning' : 'info' %>">
  Plan<%= @user.plan_id.to_s %>
</span>

Используйте этот метод в своей пользовательской модели:

def add_warning?
  self.plan_id.in?([2, 4, 6, 8])
end
person tekina    schedule 23.08.2016