terça-feira, 6 de março de 2012

Usango a gem twitter-bootstrap-rails com MongoDB

Com esse novo railscast ficou muito fácil criar um admin com um layout amigável.
Como é explicado no vídeo, basta alguns comandos e você terá todo o css gerado para sua página admin (a gem também altera algumas partes do html, que no meu caso tive que consertar).
A gem funciona perfeitamente bem quando você usa o mysql como banco de dados. Mas, e se você usar o Mongo? Foi o que aconteceu comigo, a gem simplesmente não funciona.
Analisando as mensagens de erro, descobri que o motivo estava na função columns, que é uma função estática das classes que representam os models. Algo como:

User.columns

Essa função retorna, entre outras coisas, o nome de cada coluna da respectiva tabela (no caso users) e o seu tipo, assim a gem pode montar os formulários automagicamente.
Mas como o mongo não tem esse conceito de tabela, essa função simplesmente não existe. Logo, é necessário criá-la.
Vamos lá, não é difícil. Começamos criando uma nova classe na pasta models (app/models):


class MongoDBColumn
  attr_accessor :name, :type

  def initialize args
    args.each do |k,v|
      instance_variable_set("@#{k}", v) unless v.nil?
    end
  end
end

Coloque o nome do arquivo de mongodbcolumns.rb. Essa classe simula uma coluna no mongo, assim como o mysql possui a classe Mysql2Column, que é a classe que retorna o nome e o tipo de cada coluna.

Agora, em cada model que você quiser gerar admin, você precisa criar a função estática columns. Vou citar como exemplo um model que representa os contatos que os usuários fazem (formulário de contato, ou fale conosco).

Logo no começo do arquivo contact.rb, adicione essa linha:

require 'mongodbcolumns.rb'

Depois, no final da classe (mas antes do end), cria a função columns:


def self.columns
  return Array.new([
    MongoDBColumn.new(:name => 'name', :type => :string),
    MongoDBColumn.new(:name => 'email', :type => :string),
    MongoDBColumn.new(:name => 'subject', :type => :string),
    MongoDBColumn.new(:name => 'message', :type => :text)
  ])
end

Neste caso estou simulando uma tabela com quatro columnas (name, email, subject e message), as três primeiras do tipo string e a última do tipo text (os campos no formulário vão ser gerados de acordo com o tipo da tabela, igual o scaffold faz).

Pronto, agora é só rodar o generate do bootstrap:

rails g bootstrap:themed admin/contacts -f

Estou usando admin/contacts porque quero que as views sejam geradas dentro da pasta admin. Você pode remover esse admin/ se quiser as views na pasta da aplicação mesmo.

Como eu disse no começo, o gerador altera algumas coisas nas views. No meu caso deu problema no arquivo _form.html.erb. Logo na primeira linha:

<%= form_for @contact, :html => { :class => 'form-horizontal' } do |f| %>

Como estou usando a pasta admin, minha rota é um pouco diferente. Em vez de @contact, eu utilizo [:admin, @contact]. É só alterar essa linha para:

<%= form_for [:admin, @contact], :html => { :class => 'form-horizontal' } do |f| %>

Agora está tudo funcionando.

Nenhum comentário:

Postar um comentário