Mad Mimi Gem

Mad Mimi is an email marketing service that allows users to create, send and track email campaigns in a fresh novel way without using templates.
This gem adds a Mad Mimi integration in your ruby application to deliver emails and manage your Mad Mimi audience.
Install:
gem install mad_mimi |
Documentation:
http://rdoc.info/gems/mad_mimi |
Usage Examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
require "rubygems" require "mad_mimi" # Sets the MadMimi configuration options. Best used by passing a block. MadMimi.configure do |config| config.username = "YourMadMimiEmailAddress" config.api_key = "YourMadMimiApiKey" end # Sending transactional email MadMimi.mailer.mail({ :promotion_name => "Welcome", :recipients => "Ozéias Sant'Ana <oz.santana@gmail.com>" }) # Performs an audience search and returns the up to the first 100 results. MadMimi.audience.search # Get Audience Members MadMimi.audience.members # Get all Audience Lists MadMimi.audience.lists # Add Audience List Membership MadMimi.audience.add_to_list('Clients', {:first_name => 'Ozéias', :last_name => 'Santana', :email => 'oz.santana@gmail.com'}) # Remove Audience List Membership MadMimi.audience.remove_from_list('Clients', 'oz.santana@gmail.com') # Suppress an Audience Member MadMimi.audience.suppress('oz.santana@gmail.com') |
Contributing
In the spirit of free software, everyone is encouraged to help improve this project. Here are some ways you can contribute:
- by using alpha, beta, and prerelease versions
- by reporting bugs
- by suggesting new features
- by writing or editing documentation
- by writing specifications
- by writing code (no patch is too small: fix typos, add comments, clean up inconsistent whitespace)
- by refactoring code
- by closing issues
- by reviewing patches
Submitting an Issue
We use the GitHub issue tracker to track bugs and features. Before submitting a bug report or feature request, check to make sure it hasn’t already been submitted. You can indicate support for an existing issuse by voting it up. When submitting a bug report, please include a Gist that includes a stack trace and any details that may be necessary to reproduce the bug, including your gem version, Ruby version, and operating system. Ideally, a bug report should include a pull request with failing specs.
Leave feedback, feature requests, or bugs below!
Recommend me on WWR | Follow me on Twitter
Protegendo seu código de um ataque XSS

Esta semana vários websites conhecidos como o Twitter, Orkut e o YouTube sofreram com ataques XSS.
O XSS (Cross-site scripting) é um tipo de vulnerabilidade encontrado normalmente em aplicações web que permite que crackers injetarem scripts client-side em páginas visualizadas por outros usuários. Os ataques de XSS somam aproximadamente 80% de todas as vulnerabilidades documentadas pela Symantec desde 2007. O impacto no website pode variar de um pequeno incômodo a um risco de segurança significativo, dependendo da sensibilidade dos dados tratados pelo website vulnerável e a natureza das eventuais reduções de segurança implementadas pelo proprietário do mesmo.
Ataque
Através de um XSS, o cracker injeta códigos JavaScript em um campo texto de uma página já existente e este JavaScript é apresentado para outros usuários.
Imagine que você tenha um campo de texto simples, para que o usuário possa atualizar seu status (What’s happening?) e uma tela para exibir esse status assim:
1 2 |
# form <%= f.text_field :status -%> |
1 2 |
# view <%= @user.status -%> |
Se um usuário malicioso preencher com:
<script>alert("Follow me on Twitter: @ozeias")</script> |
Se não há nenhuma proteção contra XSS, cada vez que um usuário abrir a página, vai ver o alerta:

Proteção
Até o Rails 2.3, para sanitizar qualquer entrada gerado pelo usuário, utiliza-se o método h().
1 2 |
# view <%= h @user.status -%> |
No Rails 3, por padrão, toda saída é automaticamente sanitizada e por isso não há necessidade de colocar o método h(). Caso você queira exibir a string sem sanitizar, use o método raw():
1 2 |
# view <%= raw @user.status -%> |
Para quem tem aplicação em produção usando Rails 2.3 e não quer correr o risco de esquecer de sanitizar alguma entrada de usuário, pode utilizar o plugin RailsXSS, instalando-o no seu projeto:
./script/plugin install git://github.com/rails/rails_xss.git |
Este é um assunto importante que quem desenvolve para a web precisa entender e lembrar de sempre sanitizar qualquer entrada gerada pelo usuário e isso provavelmente vai lhe poupar muito tempo no futuro.
Mais informações
Foto by Defensor Fortis
Rails 2.1.1 - Release de Manutenção

Depois do Release de Manutenção para o Rails 2.0, sai agora o Release de Manutenção para o Rails 2.1. A nova versão, 2.1.1, corrige os problemas de segurança do REXML, além de outras pequenas atualizações.
Para instalar a nova versão: gem install rails -version 2.1.1
Rails 2.0.4 - Release de Manutenção

Acaba de ser liberada a versão 2.0.4 do Rails. É uma liberação para corrigir alguns problemas de segurança, compatibilidade e correções de alguns erros. A mais importante das correções, e graças a comunidade, foi ajustar a vulnerabilidade do REXML que poderia ser usada para um ataque DoS.
Para instalar a nova versão: gem install rails -version 2.0.4
Usando o Observer no Rails
Este artigo seria apenas uma dica de como saber o que foi alterado em um objeto, mas para ficar mais fácil e principalmente para quem está dando os primeiros passos em rails resolvi fazer uma pequena introdução sobre o assunto.
O Observer é um objeto que se responsabiliza por "escutar" os eventos que ocorrem com outro objeto. Ou seja, qualquer alteração feito no objeto observado será analizado e poderá executar uma ação. Isto é muito útil para gravar logs, enviar emails e outros.
Vamos criar um projetinho para entender:
1 2 3 4 |
rails observers cd observers script/generate scaffold User name:string phone:string age:integer rake db:migrate |
Acima criamos um projeto e geramos uma entidade User e seus atributos, e migramos o banco. Vamos criar agora a entidade de log e o observer:
1 2 3 4 5 6 7 8 9 10 11 |
script/generate model Log table:string action:string field:string \
old_value:string new_value:string comments:text
exists app/models/
...
script/generate observer user
exists app/models/
exists test/unit/
create app/models/user_observer.rb
create test/unit/user_observer_test.rb
rake db:migrate
|
Feito isto precisamos "ativar" o observer, e para isto basta adicionar no config/enviroment.rb
1 2 3 4 5 6 |
# config/enviroment.rb ... # Activate observers that should always be running # config.active_record.observers = :cacher, :garbage_collector config.active_record.observers = :user_observer |
Agora podemos definir em qual momento ele vai gerar o log, antes ou depois de persistir o objeto:
- before_create, before_destroy, before_update, before_save, before_update
- after_create, after_destroy, after_update, after_save, after_update
Como tudo no rails os nomes já definem o que cada um vai fazer. Vamos gerar um log quando criar ou excluir um usuário. Para isto, vamos abrir o arquivo user_observer.rb
1 2 3 4 5 6 7 8 9 10 |
# app/models/user_observer.rb class UserObserver < ActiveRecord::Observer def after_create(user) Log.create(:table => "user", :action => "create", :comments => "New user added!") end def after_destroy(user) Log.create(:table => "user", :action => "destroy", :comments => "User removed!") end end |
Vamos acessar http://localhost:3000/users e criar um user e veja o log gerado:
1 2 3 4 5 6 |
INSERT INTO "users" ("name", "updated_at", "phone", "age", "created_at")
VALUES('First User', '2008-08-22 12:07:34', '111-1111', 20, '2008-08-22 12:07:34')
INSERT INTO "logs" ("new_value", "updated_at", "comments", "old_value", "action", "field",
"table", "created_at") VALUES(NULL, '2008-08-22 12:07:34', 'New user added!', NULL,
'create', NULL, 'user', '2008-08-22 12:07:34')
|
Simples? Muito. Agora vamos pedir para ele observar o que foi alterado em um objeto:
1 2 3 4 5 6 7 8 9 |
# app/models/user_observer.rb ... def before_update(user) user.changes.each do |key, values| Log.create(:table => "user", :action => "update", :field => key, :old_value => values.first, :new_value => values.last, :comments => "User updated!") end end ... |
O log gerado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
INSERT INTO "logs" ("new_value", "updated_at", "comments",
"old_value", "action", "field", "table", "created_at") VALUES('2008-08-22 12:29:00',
'2008-08-22 12:29:00', 'User updated!', '2008-08-22 12:07:34', 'update', 'updated_at', 'user',
'2008-08-22 12:29:00')
INSERT INTO "logs" ("new_value", "updated_at", "comments", "old_value", "action", "field",
"table", "created_at") VALUES('222-2222', '2008-08-22 12:29:00', 'User updated!', '111-1111',
'update', 'phone', 'user', '2008-08-22 12:29:00')
INSERT INTO "logs" ("new_value", "updated_at", "comments", "old_value", "action", "field",
"table", "created_at") VALUES(26, '2008-08-22 12:29:00', 'User updated!', 20, 'update',
'age', 'user', '2008-08-22 12:29:00')
UPDATE "users" SET "phone" = '222-2222', "age" = 26, "updated_at" = '2008-08-22 12:29:00'
WHERE "id" = 1
|
Aqui temos apenas uma introdução do que podemos ter com o Observer. Bons estudos.
Gem has_many_select
O problema
Estava fazendo a migração de um sistema para a versão 2.1 do rails, que usa tabelas sem qualquer normalização ou padrão de DB, e me deparei com o seguinte problema:
1 2 3 4 5 6 7 |
class HeaderSale < ActiveRecord::Base
set_table_name("cab_pedido")
set_primary_key("r_e_c_n_o_")
has_many :justifications,
:foreign_key => 'nr_pedido'
end
|
O problema é que tenho uma campo chamado 'r_e_c_n_o_' que é serial(auto incremento), mais não é uma primary key. Pra complicar eu tenho um outro campo, chamado 'cpv_pedido' que a primary key e também é auto incremento (pega o último e soma), ou seja, este banco é um "sonho" para qualquer desenvolvedor.
Quando eu faço um busca:
1 2 3 4 |
x = HeaderSale.find(:first, :conditions => 'cpv_pedido = 193514')
=> 'SELECT * FROM "cab_pedido_vendas" WHERE (cpv_pedido = 193514) LIMIT 1'
x.justifications
=> 'SELECT * FROM "justificativa" WHERE ("justificativa".nr_pedido = 307634)'
|
Mais o correto seria:
=> 'SELECT * FROM "justificativa" WHERE ("justificativa".nr_pedido = 193514)' |
Para resolver este problema, criei a gem has_many_select - não sei porque dei este nome, que temporariamente resolve o problema, já que na próxima versão do rails teremos está opção.
Como usar ?
Primeiro passo é instalar a gem:
1 2 |
gem sources -a http://gems.github.com gem install ozeias-has_many_select |
Depois no environment.rb
require 'has_many_select' |
No relacionamento do model:
1 2 3 4 5 6 7 |
class HeaderSale < ActiveRecord::Base
set_table_name("cab_pedido")
set_primary_key("r_e_c_n_o_")
has_many :justifications,
:foreign_key => 'nr_pedido', :primary_key => 'cpv_pedido'
end
|
O resultado:
1 2 3 4 |
x = HeaderSale.find(:first, :conditions => 'cpv_pedido = 193514')
=> 'SELECT * FROM "cab_pedido_vendas" WHERE (cpv_pedido = 193514) LIMIT 1'
x.justifications
=> 'SELECT * FROM "justificativa" WHERE ("justificativa".nr_pedido = 193514)'
|
E agora?
E agora, se a gem estiver sendo útil para você, não se esqueça de me recomendar no working with rails.
Sugestões, dicas e críticas são bem-vindas.
Update 22/08/2008:
Apesar de ter mudado meu login no github, o nome da gem não foi atualizado. Valeu Marcus. O correto é:
1 2 |
gem sources -a http://gems.github.com gem install ozsantana-has_many_select |
No github: http://github.com/ozeias/has_many_select/tree/master
Rails-doc
Acaba de ser lançado o site rails-doc.org, uma aplicação de documentação. Ele foi desenvolvido para que os desenvolvedores Rails tenha uma alternativa muito boa de consulta a documentação do Rails.
Existem outras diversas fontes de consultas as API do rails, mais o que chama atenção no rails-doc é ser um sistema social de documentação de código. Desenvolvedores Rails podem adicionar notas a documentação atual, basta estar registrado.
Git Branch no GEdit
Tenho usado o GEdit para desenvolver em Rails. Ele é leve, rápido e eficiente. Não preciso mais do que isto.
O grande problema era que eu estava me perdendo, e lá pelas tantas, depois de alguns commit's, não sabia em qual branch eu me encontrava. Para resolver isto, voltei a usar python e fiz um plugin que informa qual o branch atual na barra de status.
Para usar é só fazer o checkout do código fonte no GitHub e copiar os arquivos para:
~/.gnome2/gedit/plugins |
Reinicie o GEdit, vá em Edit\Preferences\plugins e ative o plugin "Git Branch". Para usa-lo basta pressionar "Ctrl + Alt + B" ou em "Tools/Git Branch" e acompanhar na barra de status o branch atual.
Pretendo agora fazer um outro plugin para executar comandos do Git no próprio GEdit.
Para quem for usar o GEdit para desenvolver em Rails recomendo instalar também:
Se o plugin estiver sendo útil para você, não esqueça de me recomendar no working with rails.
JSMask - Máscara em campo texto
Como anunciei no twitter, hoje a tarde criei um plugin para resolver alguns problemas que tínhamos com datas. Basicamente, precisávamos que os campos de datas do sistema tivessem uma máscara.
Já vinha utilizando, em um outro projeto, alguns javascripts. O grande problema que eles são "gordos" e tem muita coisa implementada de forma "estranha".
Então resolvi criar um javascript para resolver o problema. Então surgiu o JSMask 0.1, baseado no LowPro e no Xaprb.InputMask.
Em partes resolvia meu problema, mais não era integrado com Rails. Então mais alguns códigos e surgiu o Plugin JSMask 0.1.
Para demonstrar as funcionalidades do plugin, fiz um pequeno tutorial. Vamos testar ?
Preparando o ambiente
Este tutorial foi baseado no Rails 2.0, então a primeira coisa é verificar se você está utilizando a versão correta:
1 2 |
rails -v Rails 2.0.2 |
Tudo certo então vamos criar nossa aplicação para demonstração:
rails jsmask_demo |
As configurações de banco de dados ficam por conta de vocês. Vamos criar o banco:
rake db:create:all |
Vamos gerar nosso scaffold:
script/generate scaffold Schedule begin:date end:date |
Isto vai gerar os Controller, Helper, Model, Migration e os testes. Agora é só executar os migrations:
rake db:migrate |
Já temos nossa aplicação, com a inserção de datas no padrão do rails:
![]()
Instalando o plugin
O plugin está no github e para instalar:
git clone git://github.com/ozeias/js_mask.git vendor/plugins |
Para o Edge Rails (>= 2.1)
script/plugin install git://github.com/ozeias/js_mask.git |
Utilizando o Plugin
Agora é simples, vamos alterar nossas views geradas pelo scaffold e testar o plugin:
1 2 3 4 5 6 |
<!-- app/views/layouts/schedules.html.erb --> ... <title>Schedules: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> <%= javascript_include_tag :defaults, :jsmask %> ... |
1 2 3 4 5 6 7 8 |
<h1>New schedule</h1><!-- app/views/schedules/new.html.erb --> <%= error_messages_for :schedule %> <%= render :partial => @schedule, :locals => { :button_name => "Create"} %> <%= link_to 'Back', schedules_path %> |
1 2 3 4 5 6 7 8 9 10 |
<!-- app/views/schedules/edit.html.erb --> <h1>Editing schedule</h1> <%= error_messages_for :schedule %> <%= render :partial => @schedule, :locals => { :button_name => "Update"} %> <%= link_to 'Show', @schedule %> | <%= link_to 'Back', schedules_path %> |
Vamos criar um partial para ficar DRY e nele inserir a funcionalidade do plugin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- app/views/schedules/_schedule.html.erb --> <%- form_for(@schedule) do -%> <p> <b>Begin</b><br /> <%= text_field_with_js_mask :schedule, :begin, :class => 'mask_date_iso' -%> </p> <p> <b>End</b><br /> <%= text_field_with_js_mask :schedule, :end, :class => 'mask_date_iso' -%> </p> <p> <%= submit_tag button_name -%> </p> <%- end -%> |
E o resultado:
![]()
Os formatos de máscara suportados são:
- date_iso: 2008-05-23
- date_br: 21/05/2008
- time: 10:46:55
- phone: (00)0000-0000
- ssn: 000-00-0000
- visa: 0000-0000-0000-0000
A primeira versão é muito básica, vou fazer alguns ajustes e adicionar novas funcionalidades em breve. Sugestões, dicas e críticas são bem-vindas.
Source code: http://github.com/ozeias/js_mask/tree/master
Exemplo: jsmask_demo.tar.gz
Se o plugin estiver sendo útil para você, não se esqueça de me recomendar no working with rails.
Mini Curso de Rails
Ontem foi realizado o segundo mini - curso de Rails aqui em Toledo. No ano passado dei uma introdução a linguagem Ruby, mais este ano foquei no framework, e foi interessante. Tivemos um bom número de participantes e o mais importante foi saber que a galera gostou.
Foi um curso nos moldes de um blog em 15 minutos, falamos um pouco sobre o que é o Rails, desenvolvemos um mini blog e falamos sobre a melhor comunidade que já encontrei, a comunidade Rails.
Assim que tiver as fotos do evento vou postar aqui. Abaixo segue os slides da curso e o mini blog para download. Obrigado a todos que participaram.
Agora vamos tentar organizar um Paraná On Rails, já conversei com o Fábio Akita e com o Carlos Brando. O Júlio Monteiro já se dispôs a dar uma palestra e também ofereceu o Treina Tom para o evento. Tem tudo para ser um sucesso.
Agradecimentos:
- Fábio Akita - Pelos slides e pelo blog.
- James D. Davidson - Pelos fotos usadas nos slides.
Rails 2.1 RC1
O DHH acabou de fazer um pequeno anúncio no twitter sobre o lançamento do Rails 2.1 RC1. Segundo ele as gems já estão no servidor beta.
DHH: "Rails 2.1 RC1 has been tagged, the gems are on the beta server, official announcement shortly. But no need holding you back from trying it".
Para acompanhar as novidades acessem o blog do Calos Brando e sua série Edge Rails. Boas novidades estão chegado, vamos testar.
UPDATE:
Para instalar o Rails 2.1 RC1 do servidor beta, basta executar:
sudo gem install rails –source http://gems.rubyonrails.com/ |
Ou:
1 2 3 4 5 6 |
git clone git://github.com/rails/rails.git git pull git checkout v2.1.0_RC1 git checkout master rake rails:update script/dbconsole |
Hoje de manhã saiu um novo episódio do Railscast com o procedimento de atualização.
Rails escala?
A duas semanas voltou a tona a discussão de que Rails não escala. Tudo porque alguém ouviu falar que não sei quem tinha falada que o Twitter iriá mudar de Rails para qualquer outra coisa que tenha escalabilidade.
Mais que diabo é escalabilidade? O que torna uma linguagem escalável? Por que de tanto bafafá por causa de um framework?
Eu trabalho quase que 100% em Rails hoje e gosto disto. Apanhei muito das macacas de auditório e ainda hoje escuto muito, mais nada me deixa tão indignado quando falam de escalabilidade. Meu professor de Engenharia de Software, muito competente por sinal, sempre enfatizou que tudo pode escalar, depende somente de como você irá fazê-lo.
Quase sempre será possível adicionar mais hardware ou mais servidores web. A questão então não é se Rails escala, mais sim quantos servidores você irá precisar para um sistema de grande porte, quanto você vai precisar de arquitetura de rede e quantos analista cuidará de tudo isto. Pronto, você acabou de escalar.
Na entrevista (ou besteirol) do Alex Payne, ele salienta o seguinte:
"The problem is that more instances of Rails (running as part of a Mongrel cluster, in our case) means more requests to your database. At this point in time there’s no facility in Rails to talk to more than one database at a time."Na realidade o grande problema são os desenvolvedores deles, os Twitter’s estão mais ligados em publicidade e marketing do que em tecnologia. Uma boa pesquisada no Google e vão ver que é possível fazer com que um cluster conecte ao mais de banco. O resto é balela.
Portanto, o grande problema é que tem muita gente que só quer falar mal, não só de Ruby, mais de tudo que é novo e tem um futuro promissor. Um bando de incompetentes que se escondem atrás de certificações e diplomas comprados.
Assim, Ruby ou qualquer outra linguagem escala basta ser competente.
update:
Acabei de colocar a foto do Akita dando uma palestra no FISL 2008. Detalhe: juro que não sabia desta foto quando escrevi este post. A foto original está aqui e a dica foi dada pelo Leonardo Torres.
ImageScience e suas dependências
Final de semana aproveitei para atualizar meu blog para o mephisto 0.8, e dar uma 'arrumada na casa'. Segui os procedimentos de instalação e tudo ocorria muito bem quando ele reclamou a não existia da biblioteca do 'FreeImage.h'.
O problema não é só para quem vai atualizar o mephisto, mais para todos que usam o gem ImageScience, uma alternativa muito rápida ao RMagick. Vale lembrar que não é um problema do mesmo, a biblioteca freeimage é uma dependência dele, e não é exigida na instalação.
Mais vamos a resolução:
Para distros derivados do Debian
sudo gem install libfreeimage3 libfreeimage-dev |
Para demais distros
1 2 3 4 5 6 |
cd /usr/local/src sudo wget http://ftp.cica.es/ubuntu/ubuntu/pool/universe/f/freeimage/freeimage_3.9.3.orig.tar.gz sudo tar -xvf freeimage_3.9.3.orig.tar.gz cd freeimage-3.9.3.repacked/FreeImage make sudo make install |
Depois é só instalar os gems:
1 2 |
sudo gem install rubyinline sudo gem install image_science |
Simples não ?!
Gerando PDF com o RTeX no Rails
RTeX é uma biblioteca ruby usado para gerar documentos pdf usando LaTeX.
Instalação
Instalando o LaTeX
O processo de instalação é muito básico, mais para quem está começando pode complicar com um pouco. Para inicio de conversa precisamos instalar a biblioteca LaTeX no seu sistema. Em sistemas linux (testei no ubuntu):
sudo apt-get install tetex-base tetex-bin texlive-base-bin |
Instalando o RTeX
A maneira mais fácil de instalar o RTeX é usando o Rubygems:
sudo gem install rtex |
Instalando o Plugin na sua aplicação
Para usar o RTeX na sua aplicação Rails basta executar o seguinte comando:
rtex --install /caminho/da/sua/aplicação |
Este comando instalará o plugin na sua aplicação (aplicação/vendor/plugins/rtex).
Usando o RTeX
Vamos criar os arquivos:
- app/views/layouts/application.pdf.rtex
- controllers/index.pdf.rtex
- controllers/_seller.pdf.rtex
Nos arquivos:
app/controllers/reports_controller.rb
1 2 3 |
def index @sellers = Seller.find(:all) end |
app/views/layouts/application.pdf.rtex
1 2 3 4 |
\documentclass[12pt]{article}
\begin{document}
<%= yield %>
\end{document}
|
app/views/sellers/index.pdf.rtex
1 2 3 4 |
\section*{Sellers}
\begin{seller}
<%= render :partial => @sellers -%>
\end{seller}
|
app/views/sellers/_seller.pdf.rtex
\seller <%= seller.name -%> \\ |
UPDATE 24/05/2008:
Precisei fazer um novo projeto usando o rtex e me retornou o seguinte erro:
1 2 |
Template is missing Missing layout layouts/application.pdf.erb in view path /home/ozeias/workspace/ror/meuapp/app/views |
Acontece que neste tutorial eu esqueci de instalar o rtex no projeto, então basta usar o comando:
rtex -i . |
Fonte:
Rails on Lighthouse
Já está no ar o novo trac do Rails. O projeto agora está na Lighthouse.
Além do Rails, migraram também o Prototype e o Capistrano.




