Testando Javascript no Rails

Continuando os estudos com Javascript e Ruby, esses dias tive um problema bem chato: existe uma gem (muito boa, por sinal) para Rails chamada “cells“, que basicamente cria uma camada, semelhante a “mini controllers” para coisas específicas em Rails (tipo “sidebar”, “carrinhos de compra”, “menus” e outras funcionalidades que são, basicamente, fragmentos de “views”, normalmente feitas com a combinação “partials+helpers” mas que ficam relativamente difíceis de testar). Junto com o Cells, foi criado o Apotomo, uma gem para criar “widgets”, e aí que está o problema: testar um widget. Claro, é possível testá-lo com integration test, mas “unit-tests”, quando envolvem Javascript+Rails, envolvem HTML Fixtures, linguagens de teste diferentes, enfim, nada produtivo.

Aí, entrou a gem Johnson. Basicamente, é um interpretador Javascript dentro de Ruby, de forma que seja possível rodar código JS dentro do Ruby (e o resultado vem como uma Ruby String, ou um Numeric, enfim). Já falei sobre isso quando estudei “The Ruby Racer” e os testes com V8 no Ruby, até me interessei pelo “env.js”, porém na época a versão que rodava com Johson estava muito ruim ainda (e infelizmente, ainda está)

Porém, o novo Env.JS (1.3) já roda no Johnson. E está muito melhor.
(more…)

Métodos privados semelhantes a Java/C++ em Ruby

Fazia um tempo que eu não postava uma das bizarrices em Ruby, então vamos lá: esses dias, no grupo de usuários de Ruby, surgiu uma discussão muito boa sobre métodos privados e alto acoplamento. A idéia é mais ou menos assim: em Java (ou C++), ao definir um método público que chama um método privado, se você reimplementar aquele método privado, os métodos públicos herdados não são afetados. Um exemplo vale mais que mil palavras, então:

#include <stdio.h>

class Example {
    public:
    void imprimir() {
        hello();
    }

    private:
    void hello() {
        printf("Hello, world!\n");
    }
};

class Ex2: public Example {
    private:
    void hello() {
        printf("Hello, from Ex2\n");
    }
};

int main(void) {
    Ex2 e;
    e.imprimir(); //Essa linha imprime "Hello, world!"
}

Já no código Ruby equivalente:

class Example 
  def imprimir()
    hello
  end

  private
  def hello
    puts "Hello, world!"
  end
end

class Ex2 < Example 
  private
  def hello
    puts "Hello, from Ex2"
  end
end

Ex2.new.imprimir #Imprime "Hello, from Ex2"

Ou seja, reimplementar métodos privados numa subclasse pode quebrar métodos da superclasse. Embora eu considere isso uma peculiaridade da linguagem e não como um problema de acoplamento, implementação falha, ou qualquer coisa (e até, mais pra frente, pretendo escrever um post sobre o assunto de diferenças entre linguagens de programação além da sintaxe), a discussão inteira me deu uma idéia: como implementar esse comportamento em Ruby?
(more…)

Closures, Functions e Programação Funcional em Javascript

Estes dias, tive que fazer um código que achei que seria muito complicado, e que deveria rodar num browser. A idéia é que, dependendo do que foi digitado em uma determinada caixa de texto, um pedaço de uma página deveria mudar. Até aí, tudo bem, o problema é que o pedaço que deveria mudar deveria agrupar informações de outras caixas de texto, e outras regras confusas. Achei uma solução muito simples e prática, e gostaria de dividí-la. Mas antes, vamos simplificar o escopo:

Imagine que há uma página, no qual há um botão “adicionar”. Ao clicar nele, ele adiciona um “select” (sexo) e uma caixa de texto com observações ou qualquer outra coisa. Podem ser adicionados tantos elementos como se achar necessário. Para cada elemento alterado, deve ser exibido um sumário na tela de baixo (observações), digamos, concatenando o sexo e as observações. A parte difícil é: quando qualquer elemento for mudado, APENAS o sumário relativo àquele conjunto de elementos (sexo e observação) deve ser alterado, e também, quando eu estiver editando as observações (ou o sexo), o sumário deve ficar em negrito. Para simplificar (e rodar em vários browser) usarei a biblioteca Javascript chamada Prototype (não usarei o JQuery porque seria jogar uma bomba numa mosca), e a idéia é escrever apenas o código relativo às edições (porque é isso que pega). Portanto, para quem quiser, basta pegar o gist do Github http://gist.github.com/658668 para ter um esqueleto do programa (basta abrir o .html em qualquer browser).
(more…)

Monkey-Patch seguro, em Javascript

Continuando os estudos com Javascript, diversas coisas interessantes, que pareciam acessíveis apenas aos programadores de Ruby, Perl e outras linguagens mais flexíveis podem ser feitas também na linguagem. O problema é que, normalmente, é difícil de usar isso em bibliotecas que já existem, principalmente porque a maioria dos códigos em Javascript ou não seguem boas-práticas ou simplesmente são escritos de forma diferente do que vou apresentar aqui, porém vale pela dica. Um exemplo bem simples, pensando na seguinte API:

objeto = {
  valor: 10,
  incrementar: function(v) { 
    if(!v) v = 1;
    valor += v;
  },
  raizQuadrada: function() {
    Math.sqrt(incrementar(4));
  }
}

Para implementá-la, em Javascript, há várias formas. Simulando o comportamento que eu fiz no post passado, é possível usar o seguinte formato:
(more…)

Estudos com Javascript

Recentemente, comprei o livro Javascript – the Good Parts, do Douglas Crockford. A principal motivação, não vou negar, foi o node.js (e o fato que muitas pessoas na net têm falado de Javascript como uma das mais “novas” maravilhas. Mas isso fica pra outro post). O livro, embora tenha uma série de problemas (e o principal é a ausência de exemplos claros, além de dar pouca ênfase ao “Javascript way”, na minha opinião) é muito bom e traz algumas definições no mínimo diferentes sobre Javascript.

Basicamente, o que é Javascript? Javascript é orientado a objeto? Javascript é funcional? Javascript suporta classes, suporta….?

Para começar, Javascript é uma linguagem de programação com sintaxe semelhante a C++, dinâmica, com tipagem absurdamente fraca, pseudo-orientada a objetos, orientada a protótipos e funcional. Wow… um de cada vez.
(more…)

Traçando a Execução em Bibliotecas de Terceiros (em Ruby)

Ontem, acredito que esbarrei feio num bug do Ruby 1.8 (não sei se outras versões estão com o mesmo problema). Para encurtar a longa história, estava mexendo num código usando TheRubyRacer semelhante ao seguinte (nota: se você não entender o código a seguir, vale a pena dar uma olhada em meu post anterior):

class UmaClasse
  def method_missing(method, *args, &b)
    puts "Método #{method} chamado!"
    ...
  end
end

require 'v8'
context = V8::Context.new
context['classe'] = UmaClasse.new
p context.eval('classe.um_metodo')
p context.eval('classe.um_metodo = 10')

O que eu esperava, é que na linha 11, fosse impressa a mensagem “Método um_metodo chamado!”, porém o que aconteceu não foi bem isso. Quando olhei para a documentação da biblioteca, descobri que ela expõe apenas os métodos públicos por padrão, agora COMO ela fazia isso… isso já é outro problema. Então, num primeiro momento, resolvi remover todos os métodos da classe UmaClasse, e ver o que acontecia:
(more…)

Conectando Javascript e Ruby

Bom, a algum tempo vi uma biblioteca chamada Harmony, para Ruby, que tenta fazer esse processo. Porém, eu achei alguns problemas na biblioteca que meio que me impediam de usá-la do jeito que eu queria, então acabei encontrando uma outra alternativa: The Ruby Racer.

Esta biblioteca usa o interpretador V8, o mesmo usado no Google Chrome, para interpretar Javascript. Possui uma API bem simples, e consegue incorporar objetos Ruby no Javascript de uma forma bem transparente. Como exemplo, digamos que queremos expor uma classe Ruby para o Javascript. Basta usar o código a seguir:

require 'v8'

class UmaClasse
  def initialize(nome)
    @nome = nome
  end

  def imprimir_nome
    puts @nome
  end
end

js = V8::Context.new
js['uma_classe'] = UmaClasse.new
js.eval('uma_classe.imprimir_nome()')

Este código conectará, no Javascript, um objeto chamado uma_classe. Para instalar a biblioteca, um simples “gem install therubyracer” basta, na maioria das vezes. Quando isso não funciona (que nem o meu caso)…
(more…)

Validações via Javascript

Esses dias, vi na lista de Ruby on Rails um plugin chamado LiveValidations. Basicamente ele converte algumas validações do Ruby para Javascript. O problema que tive, até o momento, é que ele não segue as regras I18n do Rails, mas obedece o parâmetro :message das validações. talvez eu o utilize Read more…