Benito Serna Tips and tools for Ruby on Rails developers

Emberjs vs My frontend hacks - Actualizar Contadores

October 23, 2013

Aunque javascript no sea el lenguaje mas placentero para trabajar, hoy en día es necesario si queremos dar una agradable experiencia al utilizar una aplicación web.

Algunos prefieren escribir el html en el servidor y con javascript solo aumentar la experiencia (sprinkles of javascript), otros prefieren escribir el html en el navegador. Unos prefieren usar javascript frameworks y otros no.

Yo he provado de diferentes formas, y ahora quiero hacer una comparación entre dos diferentes implementaciones para similares funcionalidades. El primer ejemplo es en la versión web desktop de Rides, que escribe el html en el servidor y con sprikles of javascript aumenta la experiencia. Y el segundo ejemplo es la versión web mobile de Rides, que es una aplicación de Ember.js que escribe el html en el cliente y solo utiliza el servidor de Rides como un API.

Actualizar contadores con “sprinkles of javascript”

El funcionamiento es el siguiente:

Cuando el usuario responde una reseña pendiente, tanto el contador global de acciones, como el contador de reseñas pendientes deben actualizarse.

rides menu

El código actual es algo así:

<script>
new PendingReviewForm("#trip_<%= trip.id %>", "#pending_review_<%= pending_review.id %>")
</script>
class window.PendingReviewForm
  constructor: (trip_selector, pending_review_selector) ->
    @form = $ @review.find 'form'
    @global_counter  = new ActivityCounter('#pending_activity_count')
    @reviews_counter = new ActivityCounter('#pending_reviews_count')

    @form.submit (e) =>
      e.preventDefault()
      @save()

  save: ->
    $.ajax
      type: "POST"
      url: @form.attr 'action'
      data: @form.serialize()
      success: (response) =>
        @remove()
        @global_counter.decrement()
        @reviews_counter.decrement()

class window.ActivityCounter
  constructor: (selector) ->
    @counter = $ selector

  decrement: ->
    updated_val = parseInt(@counter.text(), 10) - 1

    if updated_val == 0
      @counter.remove()
    else
      @counter.text(updated_val)
<span id="pending_reviews_count" class="badge badge-important">
  <%= current_user.pending_reviews.count %>
</span>

Entre los varios problemas que tiene este código, el que yo creo mas notorio es que actualizamos el contador a ciegas y no por medio de la cantidad de reseñas pendientes.

Acutalizar contadores con Ember.js

Nota: Se esta utilizando la revisión 13 de Ember data

rides mobile menu

El funcionamiento es el siguiente:

Al contestar una pregunta pendiente, el contador de preguntas pendientes tiene que actualizarse y desaparecer, cuando ya no hay preguntas pendientes.

Con ember.js podemos lograr esto de una forma declarativa, ya que el valor se actualiza automáticamente al contestar una pregunta.

El código actual es algo así:

{{#if currentUser.questionsToAnswer}}
  <span class="navbar-menu__badge">
    {{currentUser.questionsToAnswerCount}}
  </span>
{{/if}}
App.QuestionController = Ember.ObjectController.extend
  createAnswer: ->
    body = @get 'newAnswerBody'
    return if !body.trim()

    question = @get 'model'
    answer = App.Answer.createRecord question: question, body: body

    @set 'newAnswerBody', ''
    @get('store').commit()
App.User = DS.Model.extend
  questions: DS.hasMany("App.Question")

  questionsToAnswer: (->
    @get('questions').filterProperty('hasAnswer', false)
  ).property('questions.@each.hasAnswer')

  questionsToAnswerCount: (->
    @get("questionsToAnswer").get('length')
  ).property('questionsToAnswer')

En mi opinion, ember.js permite representar la interfaz de una manera más natural, y en este caso mostrado, creo que resuelve de manera elegante, el “hack” de mi implementación con “sprinkles of javascript”.

Related articles

Weekly tips and tools for Ruby on Rails developers

I send an email each week, trying to share knowledge and fixes to common problems and struggles for ruby on rails developers, like How to fetch the latest-N-of-each record or How to test that an specific mail was sent or a Capybara cheatsheet. You can see more examples on Most recent posts or All post by topic.