joseluistorres

joseluistorres

Publicado
Julio 18, 2013

Próximos Eventos

Blog

Refactorizar a un helper

En días pasados, después de encontrar la gema de railsbestpractices como les explicaba en el post. Estuve revisando nuestro código en powhow.com e inmediatamente me di cuenta que teniamos tantísimos cosas que arreglar que de plano no terminaríamos refactorizando todo para usar las mejores prácticas.

En la reunión pasada de @ruby_gdl lo comentaba, la gema nos encontró 3200 warnings. Triste pero cierto, indudablemente nos hace falta mucho por aprender y sin duda esta herramienta es un buen comienzo. Ya entrados en materia encontré que uno de los warnings o sugerencias para refactorizar era mover código similar en una vista y moverlo a un helper. Lo había escuchado sí, lo había visto sí, lo había hecho yo mismo, no.

Veamos este es el código de diferentes vistas con una lógica similar:

Vista 1:

<% image_dimensions = process.transcoding_in_progress ? '144x81' : (process.schedule_id.nil? or !process.is_image_from_workshop) ? '144x81' : '66x81' %>
<% thumbnail_class = process.transcoding_in_progress ? 'image-container' : (process.schedule_id.nil? or !process.is_image_from_workshop) ? 'image-container video' : 'image-container process letterbox-tiny' %>
<%= image_tag !process.transcoding_in_progress ? process.thumbnail_url : Process::DEFAULT_IMAGE, :size => image_dimensions, :id => 'processplay-' + process.id.to_s, :class => thumbnail_class %>

Vista 2:

<% image_dimensions = (process.schedule_id.nil? or process.is_image_from_workshop) ? '192x108' : '88x108' %>
<% thumbnail_class = (process.schedule_id.nil? or process.is_image_from_workshop) ? 'image-container process' : 'image-container process letterbox-vsmall' %>        
<%= image_tag process.thumbnail_url, :size => image_dimensions, :class => thumbnail_class, :id => "" %> 

Vista 3

<% image_dimensions = (@process.transcoding_in_progress or @process.is_image_from_workshop) ? '192x108' : @process.schedule_id.nil? ? '192x108' : '88x108' %>
<% thumbnail_class = (@process.transcoding_in_progress or @process.is_image_from_workshop) ? 'image-container' : @process.schedule_id.nil? ? 'image-container video' : 'image-container process letterbox-vsmall' %>            
<%= image_tag !@process.transcoding_in_progress ? @process.thumbnail_url : asset_path('thumb-video.jpg'), :class => thumbnail_class, :size => image_dimensions, :id => "videoplay-" + @process.id.to_s %>

Entonces tenemos 3 vistas con lógicas similares que puede ser un buen candidato para refactorizar. ¿Por donde empezar? Pues como dice @amyhoy : empecemos por el final. No teniamos un helper para esta entidad por lo que primero creamos el archivo helper de process:

module ProcessHelper
end

Excelente, pero ¿y luego que? Pensé crear un método que tuviera la salida de la etiqueta de image_tag

def image_tag_for_process(process, place_used)
  image_dimensions = process.transcoding_in_progress ? '144x81' : (process.schedule_id.nil? or !process.is_image_from_workshop) ? '144x81' : '66x81'
  thumbnail_class = process.transcoding_in_progress ? 'image-container' : (process.schedule_id.nil? or !process.is_image_from_workshop) ? 'image-container video' : 'image-container process letterbox-tiny'
  image_tag !process.transcoding_in_progress ? process.thumbnail_url : Process::DEFAULT_IMAGE, :size => image_dimensions, :id => 'processplay-' + process.id.to_s, :class => thumbnail_class %>
end

Claro me di cuenta que necesitaba una forma para validar el alto y ancho en cada caso y además la clase de CSS que debía utilizar. Empecé por la clases de CSS, y luego el tamaño y finalmente la fuente de la imagen.

module VideosHelper
  def image_tag_for_process(process, place_used)
    image_dimensions = process.transcoding_in_progress ? '144x81' : (process.schedule_id.nil? or !process.is_image_from_workshop) ? '144x81' : '66x81'
    image_tag thumbnail_image_url_process(process.transcoding_in_progress, process.thumbnail_url, place_used),
      :size => image_dimensions,
      :id => "videoplay-#{process.id.to_s}",
      :class => thumbnail_class_process(process.transcoding_in_progress, process.is_image_from_workshop, place_used)
  end

  def thumbnail_image_url_process(transcoding_in_progress, thumbnail_url, place_used)
    !transcoding_in_progress ? thumbnail_url : Process::DEFAULT_THUMBNAIL_IMAGE
  end

  def thumbnail_class_process(transcoding_in_progress, is_image_from_workshop, place_used)
    if place_used=='send_video_invite'
      if transcoding_in_progress or !is_image_from_workshop
        'image-container process process_thumb_for_mailing'
      else
        'image-container process process_thumb_for_mailing_with_letterbox'
      end
    elsif transcoding_in_progress
      'image-container'
    elsif !is_image_from_workshop
      'image-container process'
    else
      "image-container process #{letter_box_class(place_used)}"
    end
  end

  def letter_box_class(place_used)
    case place_used
    when 'manage_processes'
      'letterbox-tiny'
    when 'library'
      'letterbox-small'
    when 'locked_process'
      'letterbox-vsmall'
    when 'show'
      'letterbox'
    end
  end
end

Finalmente agregué este método al helper

def image_dimensions_process(transcoding_in_progress, is_image_from_workshop, place_used)
  case place_used
  when 'manage_processes'
    if transcoding_in_progress or !is_image_from_workshop
      '144x81'
    else
      '66x81'
    end
  when 'library'
    if transcoding_in_progress or !is_image_from_workshop
      '284x160'
    else
      '131x160'
    end
  when 'locked_process'
    if transcoding_in_progress or !is_image_from_workshop
      '192x108'
    else
      '88x108'
    end
  when 'show'
    if transcoding_in_progress or !is_image_from_workshop
      '728x410'
    else
      '335x410'
    end
  when 'send_process_invite'
    if transcoding_in_progress or !is_image_from_workshop
      '550x310'
    else
      '252x310'
    end
  end
end

Entonces finalmente la refactorización quedó así:

module VideosHelper
  def image_tag_for_process(process, place_used)
    image_dimensions = process.transcoding_in_progress ? '144x81' : (process.schedule_id.nil? or !process.is_image_from_workshop) ? '144x81' : '66x81'
    image_tag thumbnail_image_url_process(process.transcoding_in_progress, process.thumbnail_url, place_used),
      :size => image_dimensions,
      :id => "videoplay-#{process.id.to_s}",
      :class => thumbnail_class_process(process.transcoding_in_progress, process.is_image_from_workshop, place_used)
  end

  def thumbnail_image_url_process(transcoding_in_progress, thumbnail_url, place_used)
    !transcoding_in_progress ? thumbnail_url : Process::DEFAULT_THUMBNAIL_IMAGE
  end

  def thumbnail_class_process(transcoding_in_progress, is_image_from_workshop, place_used)
    if place_used=='send_video_invite'
      if transcoding_in_progress or !is_image_from_workshop
        'image-container process process_thumb_for_mailing'
      else
        'image-container process process_thumb_for_mailing_with_letterbox'
      end
    elsif transcoding_in_progress
      'image-container'
    elsif !is_image_from_workshop
      'image-container process'
    else
      "image-container process #{letter_box_class(place_used)}"
    end
  end

  def letter_box_class(place_used)
    case place_used
    when 'manage_processes'
      'letterbox-tiny'
    when 'library'
      'letterbox-small'
    when 'locked_process'
      'letterbox-vsmall'
    when 'show'
      'letterbox'
    end
  end

  def image_dimensions_process(transcoding_in_progress, is_image_from_workshop, place_used)
    case place_used
    when 'manage_processes'
      if transcoding_in_progress or !is_image_from_workshop
        '144x81'
      else
        '66x81'
      end
    when 'library'
      if transcoding_in_progress or !is_image_from_workshop
        '284x160'
      else
        '131x160'
      end
    when 'locked_process'
      if transcoding_in_progress or !is_image_from_workshop
        '192x108'
      else
        '88x108'
      end
    when 'show'
      if transcoding_in_progress or !is_image_from_workshop
        '728x410'
      else
        '335x410'
      end
    when 'send_process_invite'
      if transcoding_in_progress or !is_image_from_workshop
        '550x310'
      else
        '252x310'
      end
    end
  end

end

Y la implementación:

<%= image_tag_for_video video, 'manage_videos' %>
<%= image_tag_for_video video, 'library' %>
<%= image_tag_for_video video, 'locked_video' %>

Aún no sé si es la mejor opción pero por ahora se ve mejor y entiendo mejor que estaba haciendo. ¿Y ustedes como lo mejorarían?

José Luis Torres, trabaja como Ingeniero Ruby on Rails en Powhow, sigue a José Luis en twitter @joseluis_torres