Image Upload for Redactor with Ruby on Rails

Redactor is an awesome wysiwyg editor, and one of its features is image uploading. To do that, according to their (also awesome) documentation, you need to setup a service to receive a post request with the image to upload, and respond with a specific json.

The implementation of that service on your existent Ruby on Rails application is fairly simple. I’ll assume you have basic Rails knowledge, and you’re familiar with Carrierwave, a Ruby library to handle file uploads. Also, I’ll be presenting an example code.

So, first step, you may need to generate a controller to handle that service.

rails g controller images

Next, setup a route for it:

post 'images/upload', to: 'images#upload_image', as: 'upload_image'

A sample code for the controller may be as such:

class ImagesController < ApplicationController
  skip_before_filter :verify_authenticity_token, only: [:upload]
  def upload
    uploader = TemporaryImageUploader.new #your uploader
    uploader.store!(params[:file])
    file_url = request.protocol + request.host_with_port + uploader.url
    render json: [{ filelink: file_url }]
  end
end

A few notes on the code above: please note the skip_before_filter part – without it, your app may lose the authentication session after the request from Redactor.

For the javascript, just add the imageUpload parameter and set it to your image_upload_url path, defined on the routes.

And that’s it.

Zend Music Collection

Quando comecei a estudar o Zend Framework, senti muita falta de uma aplicação de exemplo que usasse alguns dos recursos que tanto lia sobre, como o Zend_Acl, Zend_Navigation, Zend_Paginator, entre outros. O tempo passou, eu acabei aprendendo a usar esses componentes graças principalmente a posts em blogs de colegas, ensinando a usá-los em situações mais próximas das que encontramos no dia-a-dia.

Então, resolvi criar uma aplicação bem básica, mas que usa boa parte dos componentes “básicos” do framework. Chama Zend Music Collection (nome péssimo, eu sei…), e é um sistema que cadastra artistas e seus álbuns. Simples, né? Aqui uma lista de componentes que ela utiliza:

  • Zend_Navigation (menu & breadcrumbs)
  • Zend_Layout
  • Zend_Paginator
  • Zend_Form
  • Zend_Controller_Action_Helper_FlashMessenger
  • Zend_Db_Table
  • Zend_Auth

Junto com a aplicação vem um arquivo com a SQL de criação do banco de dados. Tentei comentar cada instrução não óbvia do código, principalmente dos controllers, para tentar melhor explicar afinal de contas o que está acontecendo por ali. Espero que essa aplicação possa ajudar outras pessoas a ter uma introdução mais rapida e tranquila ao Zend Framework, e também espero que nenhuma pessoa resolva usar ela para cadastrar sua coleção de músicas – seria uma péssima idéia.

A Zend Music Collection, e todo o seu código-fonte, está disponível no GitHub.

Best Movies Watchlist

Chrome Web Store, para quem não conhece, é uma loja de aplicativos que rodam dentro do Google Chrome (webapps). Com as novas tecnologias (principalmente HTML5) já é possível desenvolver webapps com uma ótima qualidade e que chegam cada vez mais próximas, principalmente na performance e no “look and feel”, dos aplicativos desktop.

Desde seu lançamento estive pensando em desenvolver uma webapp, principalmente para ter uma experiência prática com esse novo paradigma. Queria fazer algo que fosse útil para outras pessoas, e não só um aplicativo experimental descartável. Como bom cinéfilo, estou sempre de olho nas listas de “top movies” em busca de bons filmes que ainda não assisti. Daí veio a idéia da Best Movies Watchlist: uma webapp que traz sempre a lista atualizada de “top movies”, e me permite marcar os que já assisti. Simples e objetiva, e resolve em cheio o meu “problema”.

Neste post irei relatar como foi o processo de desenvolvimento dessa webapp, que você pode conferir já na webstore.

1. Documentação

2. Estrutura Inicial

Primeiro, criei um diretório chamado best-movies-watchlist no meu Desktop, estruturado da seguinte forma:

best-movies-watchlist/
    css/
        style.css
    img/
    js/
    icon_16.png
    icon_32.png
    icon_128.png
    index.html

Depois disso, conforme indicado pela documentação, criei um arquivo chamado manifest.json dentro da pasta best-movies-watchlist com o seguinte conteúdo:

{
    "name": "Best Movies Watchlist",
    "version" : "0.1",
    "description": "Watchlist from the best movies of all time!",
    "icons": {
        "16": "icon_16.png",
        "32": "icon_32.png",
        "128": "icon_128.png"
    },
    "app": {
        "launch": {
            "local_path": "index.html"
        }
    }
}

O manifest é um json que indica, basicamente,  os dados gerais da aplicação (incluíndo os ícones) e o arquivo a ser “chamado” quando a webapp for lançada (index.html).  Até agora, bem simples.

3. HTML (5)

Como boa fonte de pesquisa, me guiei pelo ótimo artigo da Smashing Magazine sobre HTML5: Coding a HTML5 Layout From the Scratch. Utilizei, basicamente, as novas tags header, section, article, aside e footer para melhor descrever a marcação da página. O resultado final do HTML você pode visualizar aqui.

4. Javascript

Toda a “mágica” da webapp vai ser realizada pelo Javascript. Carreguei o jQuery no HTML e agora é colocar as mãos na massa.

Para pegar a lista de filmes de outros sites, vou “esbarrar” em um problema: tenho que respeitar a Same Origin Policy, que previne cross-site scripting. Utilizarei então um serviço do Yahoo chamado YQL, que permite realizar o cross-site-scripting e, de quebra, ainda me permite fazer buscas no conteúdo de páginas web de uma maneira mais simples. O que tenho que fazer, então, é uma chamada ajax para o serviço de YQL do yahoo com os parâmetros da minha consulta, exibir os resultados em uma tabela e voilá.

Porém, de onde irei puxar a lista de filmes? Meu primeiro pensamento é o IMDb, cuja lista de Top 250 é a, talvez, mais confiável. Só que, infelizmente, não é permitido usar “robôs” e semelhantes para extrair informações das páginas web do IMDb. Próximo da lista então. Descobri dois IMDB-alikes: OMDB e TMDB, que permitem extração de informações, ao contrário do IMDb.

Abaixo um pedaço de código que ilustra uma chamada ajax para o YQL em busca da lista de top movies do OMDB:

function loadDataFromOmdb() {
    var movieList = new Array();
    // Fetching Data from http://www.omdb.org/movie/top
    var url = "http://www.omdb.org/movie/top";
    var sanitizedUrl = sanitizeUrl(url);
    $.getJSON("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + sanitizedUrl + "%22%20and%20xpath%3D'%2F%2Ftable%5B%40id%3D%22filmography%22%5D%2F%2Ftr'&format=json&diagnostics=true&callback=?", function(data){
        if (!data.query || !data.query.results) {
            showInitError();
        } else {
            $.each(data.query.results.tr, function(i,item){
                if (item.td) {
                    var movie = {
                         ranking: ++i,
                         title: item.td[1].a.content,
                         url: "http://www.omdb.org" + item.td[1].a.href,
                         rating: item.td[2].p,
                         year: ''
                    }
                    movieList.push(movie)
                }
            });
            setMovieList(movieList);
            setSource('www.omdb.org');
            renderContent(movieList);
        }
     });
}

A query YQL utilizada neste exemplo, para fins de melhor leitura, foi a seguinte:

select * from html where url="http://www.omdb.org/movie/top" and xpath='//table[@id="filmography"]//tr'

Estou pegando todas as TR (table row) dentro da tabela de id “filmography” do site www.omdb.org/movie/top. Bem intuitiva, né? Depois disso eu as coloco em um array e o passo para a função renderContent, que irá renderizá-lo na tabela definida no HTML.

Agora a webapp irá exibir a lista dos filmes, com a opção do usuário marcar os que ele já viu. Próximo passo agora é fazer com que essa definição dos filmes já vistos seja persistida, para quando o usuario abrir e fechar o browser, ou até reiniciar o computador, sua lista continue indicando os filmes que ele já viu. Para atingirmos isso iremos utilizar mais um recurso do HTML5: localStorage, que nos permite gravar dados (simples) em um banco de dados local, implementado pelo browser conforme as definições da W3. Sempre que o usuario marcar ou desmarcar um filme, a database será atualizada com o valor daquele filme. Abaixo um pedaço do código necessário para isso:

function setMovieStatus(movieId, status) {
    localStorage["best-movies-watchlist." + movieId] = status;
}

O banco de dados é acessado da maneira mais simples possível: localStorage[nomeDoCampo] = valor. Para recuperar um valor salvo, a sintaxe é semelhante: valorSalvo = localStorage[nomeDoCampo].

Para que a webapp funcione offline, precisarei ter uma cópia da lista salva localmente. Irei tentar atualizá-la com a fonte escolhida 1x por dia e, caso consiga, irei converter o array movieList para JSON e salvá-lo localmente, já que o localStorage só salva “texto”. Nas próximas utilizações do usuário nesse dia, a webapp irá trazer a lista salva localmente, convertê-la de JSON para um array novamente e plotá-la na tela — dessa forma temos a webapp funcionando em um cenário pós-apocalíptico offline.

Além desses recursos, também implementei alguns outros para deixar a webapp mais robusta, como:

  • Opção de trocar a fonte da lista de filmes
  • Sugerir filmes com base nos filmes já assistidos
  • Opção de exibir somente filmes não assistidos
  • Exibir quantos filmes foram assistidos e quantos não foram
  • Botão para “resetar” a webapp ao seu estágio inicial
  • Seleção de tema para a webapp, e persistindo a escolha no localStorage

Mais detalhes da implementação de cada um desses recursos podem ser vistos na página do projeto no github.

5. Carregando a Webapp no Google Chrome

Para carregar uma webapp em desenvolvimento no Chrome, abra o mesmo e vá para a url chrome://extensions. Lá habilite o modo Developer Mode, clique no botão Load unpacked extension e escolha a pasta raiz da webapp. Pronto, é isso. :)

6. Publicando na Webstore

Para publicar a webapp na Web Store é interessante ler a documentação, que já basicamente especifica tudo que precisa ser feito. Vale a pena lembrar, porém, que é necessário pagar uma taxa de 5$ para poder enviar suas webapps para a store.

A Best Movies Watchlist, exemplo deste post, está disponível na Web Store e todo o seu código fonte está disponível no GitHub. Quaisquer sugestões e/ou críticas serão bem-vindas! :)

Tema WordPress: Ghostwriter

Ghostwriter: clean and minimalistic theme for WordPress

Depois de usar magníficos temas criados pela participativa comunidade do WordPress, decidi criar um próprio e compartilhá-lo de volta. O tema chama-se Ghostwriter (título em homenagem ao ótimo filme de Roman Polanski), e sua proposta é ser um tema minimalista, limpo, focado no conteúdo e o seu mojo é a tipografia — graças à fabulosa fonte Gentium e ao seletor @font-face do CSS3, ou seja, somente browsers mais “modernos” irão carregar essa maravilha. Mas não priemos cânico criemos pânico! Preparei algumas outras boas fontes no css para entrarem caso o browser seja antigo não consiga carregá-la.

Escreverei as features em inglês, pois acho mais elegante. 😛

Features:

  • HTML5 markup
  • Awesome Typography
  • Clean and minimalistic approach
  • Full Internationalization
  • Support for widgets on the sidebar
  • Tested on IE6+, Google Chrome, Safari and Firefox

Preview: o próprio blog está com o tema! \o/

Versão atual: 1.4 (15 Janeiro 2011)

Download: clique aqui

Webservices com Grails

Grails é um ótimo framework para aplicações web em Groovy (linguagem dinâmica para Java). Seu foco é alta produtividade e simples configuração o que, na minha humilde opinião, vêm fazendo com tal maestria que merece um #epicwin.

Mas vamos ao que interessa: como montar um Webservice com o Grails.

1. Instalando o Plugin

Usaremos o xfire como o nosso framework para SOAP. Primeiro, instale o plugin xfire para sua aplicação Grails, com o seguinte comando:

grails install-plugin xfire

Mais fácil, impossível.

2. Criando o service inicial

Na pasta da aplicação, digite o seguinte comando pelo terminal para criar um service do Grails (usarei o nome “Webservice” só para fins de aprendizado):

grails create-service Webservice

Pronto, o grails agora criou um service na pasta grails-app/services/. Agora abra o service criado em seu editor de texto favorito e insira a seguinte linha em cima (ou substitua, como preferir) da linha static transational = true:

static expose=['xfire']

Com isso o seu service já está pronto para ser consumido. Execute sua aplicação (comando grails run-app) e o wsdl do seu webservice poderá ser acessado pela url (caso sua aplicação esteja em localhost:8080/Exemplo):

http://localhost:8080/Exemplo/services/webservice?wsdl

Uma dica é usar o soapUI para testar o seu webservice.

3. Listando Domain Classes

Agora que o seu webservice já está up and running, vamos criar um novo serviço para, por exemplo, listar os registros de uma domain class do grails. Suponhamos que exista uma domain class chamada Livro e outra chamada Autor. Um Autor possui vários livros (hasMany, no Grails) e um Livro possui um Autor (atributo do tipo Autor). Para evitar referências circulares na conversão das domain classes para XML, adicione a seguinte linha acima dos atributos à(s) domain class(es) com a ligação do tipo “belongs to” (no nosso caso, Livro):

static xmlTransients = ['autor']

Onde [‘autor’] é o nome do atributo do tipo Autor da domain class em questão.

Voltando ao WebserviceService, vamos acrescentar o método listarLivros():

Livro[] listarLivros() {
    Livro.list() as Livro[]
}
Acessando esse serviço, este é um exemplo do que ele irá retornar:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap:Body>
        <ns1:listarLivrosResponse xmlns:ns1="http://exemplo">
            <ns1:out>
                <ns1:Livro>
                    <id xmlns="http://exemplo">1</id>
                    <nome xmlns="http://exemplo">Senhor dos Aneis</nome>
                    <version xmlns="http://exemplo">0</version>
                </ns1:Livro>
                <ns1:Livro>
                    <id xmlns="http://exemplo">2</id>
                    <nome xmlns="http://exemplo">Hobbit</nome>
                    <version xmlns="http://exemplo">0</version>
                </ns1:Livro>
            </ns1:out>
        </ns1:listarLivrosResponse>
    </soap:Body>
</soap:Envelope>

A conversão da domain class para XML foi feita pelo Grails de forma automágica.

Isso conclui um webservice básico em Grails. Simples, né? :)

Autenticando o Zend Framework no Alfresco

O Alfresco, em poucas palavras, é um GED (Gerenciador Eletrônico de Documentos) escrito em Java e que possibilita gerenciamento inteligente dos documentos, buscas à la Google e integração com diversas interfaces. Possui uma versão Community, que é gratuita e open-source. O Alfresco também possibilita a criação e desenvolvimento de sistemas em cima de sua plataforma, através dos seus Web Scripts. Esses scripts ficam disponíveis como serviços REST para serem consumidos por outras aplicações.

No caso de uma aplicação derivada do Alfresco, pode ser interessante que ela faça sua autenticação diretamente no próprio. O módulo Zend_Auth, do Zend Framework, pode ser extendido para realizar sua autenticação em diversas plataformas. Desenvolvi então um Adapter para o Zend_Auth para autenticar no Alfresco, utilizando o Webservice de autenticação que o mesmo disponibiliza.

Para os interessados em utilizar/expandir/melhorar a classe, aqui está o link para o projeto no Github. Em breve irei postar mais conteúdos sobre integraçao do Zend Framework com o Alfresco, principalmente classes para utilizar seus serviços REST nativos, como listagem de usuarios, grupos, pastas e arquivos.

Link: Zend_Auth_Adapter_Alfresco

PHP Conference Brasil 2010

A PHP Conference Brasil é um dos eventos de referência no que  se refere a PHP no Brasil. A sua quinta edição acontecerá nos dias 25 à 28 de Novembro em Osasco – SP. Ao tempo de escrita desse post (15/09/10), a programação do evento ainda não está definida, mas podemos esperar algumas ótimas palestras sobre Zend Framework, WordPress e outros temas mais “consagrados” do PHP. Talvez até algo sobre PHP6? Seria bem interessante.

Especulações a parte, nós – programadores PHP – devemos sempre dar suporte à esse tipo de evento, é uma grande oportunidade de observar o que está bombando lá fora, fortalecer a nossa comunidade de desenvolvedores e trocar algumas figurinhas com outros programadores/entusiastas da linguagem.

Para mais informações, visite o esquisito site do evento: http://www.temporealeventos.com.br/?area=13

Framework para CSS: Blueprint

Se você tem criado arquivos CSS há um tempo, pode ter ficado frustrado por sempre ter que recriar e re-testar layouts básicos com alguma frequência. A discrepância/diferenças entre os browsers atuais também é algo que pode causar um stress atraso no desenvolvimento do estilo do site, principalmente quando não se tem tanta familiaridade com os hacks para tratar esses problemas. Com o tempo, é possível “quebrar” a folha de estilo em componentes reutilizáveis em vários projetos, todos otimizados e testados em vários browsers/plataformas. O próximo passo é, com a evolução desses componentes, criar um pacote e utilizá-lo como base para desenvolvimento de novos layouts. Pois, esse pacote é exatamente o que o Blueprint, framework para CSS, se propõe a ser — de graça. Legal, não?

Abaixo, alguns dos recursos que o Blueprint oferece, com um link para uma demonstração:

Dependendo do seu projeto, pode ser mais interessante utilizar todo o Blueprint, ou somente algum componente, como formulários ou tipografia. Além dele, também existem outros frameworks de CSS com uma proposta parecida, como o Tripoli e o Elements.

Zend Framework Coding Standards

Para produzir um código de alta qualidade, um bom início é seguir algum padrão de codificação. Ele melhora a legibilidade, torna o código mais previsível e ajuda na sua manutenção.

Devo colocar as chaves de abertura de um método na mesma linha, ou devo quebrar uma linha? Quantos espaços utilizar para identar o código? Qual deve ser tamanho máximo de cada linha de código?

É interessante que a resposta para cada uma dessas e outras perguntas sobre padrões de código seja a mesma ao longo de todo o sistema. Não é agradável ver, por exemplo, duas classes do mesmo sistema com diferentes tamanhos de identação ou uma classe com o tamanho máximo de linha de 80 caracteres e outra sem nenhum limite definido. Aliás, que derrota é abrir um arquivo sem limite de tamanho das linhas, com aquela horrível barra de rolagem horizontal. A impressão que causa é que o autor do código não se importava muito com ele, e isso é um péssimo presságio que coloca em dúvida a qualidade do código do restante do sistema.

A Zend, a auto-intitulada “The PHP Company”, criou um padrão bem interessante, bem documentado e suuuper legal. Para os usuários do Zend Studio, é possível até definir esse padrão para a IDE pelo caminho: Window > Preferences > PHP > Code Style > Formatter > Active Profile.

Para os interessados, segue o link da documentação do padrão de código PHP da Zend: Zend Framework Coding Standards.