Criando um formulário de contato simples usando o ActiveRecord

Se você já utilizou o Rails alguma vez, certamente também usou (e provavelmente adorou) a implementação Model-View-Controller (MVC) que existe a sua disposição.

Nela podemos representar facilmente uma tabela em um banco de dados como um objeto qualquer. Esta transformação permite a você manipular, editar, consultar, listar, etc... com facilidade as informações contidas na sua tabela.

Eu estive pensando em criar um formulário de contato simples. Porém, sem usar uma tabela no banco de dados (que não faz sentido algum nesse caso) como eu poderia me aproveitar das vantagens do ActiveRecord?

Só pra dar uma visão geral sobre o ActiveRecord: é ele quem vai dar a você todos os facilitadores na hora de trabalhar com um modelo que representa uma tabela em seu banco de dados.

Como você já deve estar imaginando, estas facilidades só estarão disponíveis, por padrão, se os seus dados estiverem dentro de uma tabela para que o Rails possa ler eles e transformá-los num objeto para você.

Pensando nisso, fiz uma pesquisa e encontrei uma solução que permite criar um modelo que define os campos diretamente, sem a necessidade de uma tabela real. Eu achei um PDF com o artigo, a URL indicada no final do PDF não existe mais. Apenas encontrei referências em um fórum. ;)

Criando um modelo que apenas simula uma tabela

O primeiro passo é criarmos um modelo que nos vai permitir criar outros modelos que não estejam ligados a tabela alguma. O modelo é simples e não precisa de alteração alguma:

class TablelessForms < ActiveRecord::Base
def self.columns()
@columns ||= [];
end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(
name.to_s, default, sql_type.to_s, null
)
end
# override the save method to prevent exceptions.
def save(validate = true)
validate ? valid? : true
end
end

Basta salvá-lo dentro da sua pasta de modelos (app/models) e pronto. Agora você pode criar um outro modelo para representar sua pseudo-tabela:

class ContactForm < TablelessForms

column :name, :string
column :email, :string
column :site, :string
column :subject, :string
column :message_text, :text

validates_presence_of :name,
:message => 'Seu nome (campo obrigatório)'
validates_format_of :email,
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:message => 'Seu e-mail (formato inválido)'
validates_presence_of :subject,
:message => 'O assunto (campo obrigatório)'
validates_presence_of :message_text,
:message => 'Sua mensagem (campo obrigatório)'

end

Repare que eu criei ali meus campos usando o column. Criei de acordo com os campos que eu queria em meu formulário.

Aproveitei e adicionei também todos os métodos de validação necessários ao meu formulário. Pronto, temos o nosso modelo pronto para uso.

Usando o modelo em uma action

Agora a parte mais fácil. Se você já usou algum modelo para manipular dados com o Rails vai notar que o funcionamento é basicamente o mesmo, a diferença é que os dados não irão para o banco. =)

Vamos criar uma action para mostrar o nosso formulário ou enviar os dados (caso o formulário seja enviado):

def contato
# se o método é get, o formulário ainda não foi enviado, mostramos o form vazio
if request.get?
@contact = ContactForm.new
else
# aqui recebemos o formulário por post, vamos criar o nosso objeto
# usando os parâmetros vindos do formulário
@contact = ContactForm.new( params['contact'] )
# o método save (que foi sobreescrito) vai ativar a validação
if @contact.save
# se está tudo OK com os dados, vamos enviar o e-mail e...
GenericMailer.deliver_contact_me @contact
# ... redirecionar mostrando uma mensagem
display_message 'Sua mensagem foi enviada com sucesso!', 'app-ok', '/mostrar/contato'
end
end
end

O template de contato ficou assim (apenas a parte relevante, claro):

<%= form_tag( { :method => 'post' }, :id => 'contact-me-form' )%>

<%= error_messages_for 'contact' %>

<!--[form:contact]-->

<p class="hint-form">
* campos obrigatórios
</p>

<div class="fields">
<label class="labels" for="contact_name">
Nome <small>*</small>:
</label>
<%= text_field 'contact', 'name', :class => 'data-field' %>
</div>

<div class="fields">
<label class="labels" for="contact_site">
Site:
</label>
<%= text_field 'contact', 'site', :class => 'data-field' %>
</div>

<div class="fields">
<label class="labels" for="contact_email">
E-mail <small>*</small>:
</label>
<%= text_field 'contact', 'email', :class => 'data-field' %>
</div>

<div class="fields">
<label class="labels" for="contact_subject">
Assunto <small>*</small>:
</label>
<%= text_field 'contact', 'subject', :class => 'data-field' %>
</div>

<div class="fields">
<label class="labels" for="contact_message_text">
Mensagem <small>*</small>:
</label>
<%= text_area 'contact', 'message_text', :class => 'post-field' %>
</div>

<!--[eoform:comment]-->

<p class="actions">
<%= submit_tag 'Enviar' %>
</p>

<%= end_form_tag %>

E aquele método save ali?

Se você reparar no código da classe TablelessForms, ali o método save é sobreescrito.

Ele apenas vai fazer a validação sem tentar fazer alteração alguma no banco (o que geraria erros pois o que temos é uma pseudo-tabela, não uma tabela real).

Mas e o envio do e-mail?

Enviar e-mails é bastante descomplicado mas, por questão de organização, vou deixar isso como assunto para um próximo post. =)

Resumindo

Usar a estrutura do ActiveRecord para uma pseudo-tabela foi bem tranquilo de se conseguir. E com os facilitadores que o ActiveRecord permite, gerar o formulário de contato simples foi realmente simples! (com o perdão da redundância! =)

Referências
Rails
Model-View-Controller
Sobre o ActiveRecord
Métodos gerais disponíveis no ActiveRecord
O artigo original ensinando a técnica (em PDF)
Métodos de validação no ActiveRecord
Enviando e-mails

comentários (1)

Um blog com Ruby on Rails

Após um bom tempo longe do mundo dos blogs, eu estou de volta e dessa vez é pra ficar! =)

Aproveitei as férias do trabalho para aprender uma linguagem nova que pudesse substituir meu bom e velho PHP.

Não que o PHP não seja uma linguagem boa, longe disso. O fato é que eu precisava de uma linguagem que fizesse mais por mim e, por consequência, eu codifique menos. :D Foi aí que o Ruby (on Rails) surgiu na minha vida.

Os motivos

Na faculdade eu havia visto um pouco sobre Python. Gostei da sintaxe da linguagem em relação ao PHP porém não senti nela um potencial para substituir o PHP e suas inúmeras funções built-in.

No trabalho, sob uma influência bastante positiva do meu amigo Ferdinando, eu resolvi que iria apostar no Ruby on Rails. O resultado não poderia ter sido mais positivo!

As fontes

Inicialmente, comecei lendo os famosos "getting started" que achei em vários sites, exemplos: http://www.ruby-lang.org/en/documentation/ e http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html.

Depois disso parti para a leitura dos tutoriais em PDF que o Eustáquio Rangel disponibilizou em seu site. Os PDFs foram bem bacanas e permitiram uma visão geral sobre Ruby (e Rails)..

Minha principal fonte de leitura e aprendizado foi o livro: Agile Web Development with Rails. Apesar deste não ter sido o melhor livro sobre programação que eu já li, certamente ele é bem claro na maior parte dos textos.

O resultado

O primeiro resultado... bem, você está olhando para ele agora! Para praticar o que eu havia visto, resolvi construir um blog!

Peguei papel e caneta e comecei a desenhar os fluxos de navegação. Rascunhei as páginas individualmente e defini como seriam todos os comportamentos. Decidi que o projeto só estaria completo se eu cumprisse todos os requisitos que eu havia descrito.

No final das contas, o resultado ficou além do que eu mesmo havia proposto e o melhor de tudo: eu levei apenas 6 dias para fazer o blog todo, inclusive o layout!

Levando em consideração que esta é a primeira vez que faço algo com Ruby on Rails, é um resultado impressionante.

Obviamente não criei um novo WordPress. O blog é simples mas funciona! =)

Resumindo

Se você chegou até aqui pesquisando sobre Ruby on Rails, fica a minha opinião: é ótimo!

Particularmente, eu não sou muito fã de usar grandes códigos prontos. Mas o Rails é tão bem escrito que as coisas se tornam pateticamente claras e fáceis. Basicamente ele faz todo o trabalho sujo e chato, deixando você focado nos códigos e na lógica.

Tudo isso combinado com a sintaxe limpa do Ruby vai gerar um código limpo e simples, com realmente muitas linhas de código a menos que um código em PHP, por exemplo.

Referências
Ruby
Rails
PDFs sobre Ruby e Rails do Eustáquio Rangel
Agile Web Development with Rails

comentários (1)