Posts Tagged ‘action’

Ruby on Rails enviando e-mails usando o Google Apps

Postado em 31 jul 2009
Categoria(s) Ruby on Rails

Depois de algumas horas quebrando a cabeça, consegui fazer funcionar o envio de e-mails usando o Google Apps.

Vou explicar como configurar. ;-)
Vamos lá!

Configure o config/environment.rb

Configure o seu environment.rb com a sua conta de e-mail do Google Apps, ou conta do Gmail, os e-mails serão enviados via smtp.

1
2
3
4
5
6
7
8
9
10
11
12
...
Rails::Initializer.run do |config|
...
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => "smtp.gmail.com",
    :port => 587,
    :authentication => :plain,
    :user_name => "seu-usuario@seudominio.com",
    :password => "sua senha"
  }
end

Mas só fazendo isso não vai funcionar, o Google Apps utiliza TLS (Transport Layer Security), ou seja, Protocolo de Camada de Sockets Segura.

Para funcionar é necessário adicionar a lib smtp_tls.rb responsável pela camada TLS, você encontra ela no seguinte endereço: http://github.com/patrickespake/SMTP-TLS/tree/master.

smtp_tls.rb

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
require "openssl"
require "net/smtp"
 
Net::SMTP.class_eval do
  private
  def do_start(helodomain, user, secret, authtype)
    raise IOError, 'SMTP session already started' if @started
    #check_auth_args user, secret, authtype if user or secret
    check_auth_args user, secret
 
    sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
    @socket = Net::InternetMessageIO.new(sock)
    @socket.read_timeout = 60 #@read_timeout
 
    check_response(critical { recv_response() })
    do_helo(helodomain)
 
    if starttls
      raise 'openssl library not installed' unless defined?(OpenSSL)
      ssl = OpenSSL::SSL::SSLSocket.new(sock)
      ssl.sync_close = true
      ssl.connect
      @socket = Net::InternetMessageIO.new(ssl)
      @socket.read_timeout = 60 #@read_timeout
      do_helo(helodomain)
    end
 
    authenticate user, secret, authtype if user
    @started = true
  ensure
    unless @started
      # authentication failed, cancel connection.
      @socket.close if not @started and @socket and not @socket.closed?
      @socket = nil
    end
  end
 
  def do_helo(helodomain)
    begin
      if @esmtp
        ehlo helodomain
      else
        helo helodomain
      end
    rescue Net::ProtocolError
      if @esmtp
        @esmtp = false
        @error_occured = false
        retry
      end
      raise
    end
  end
 
  def starttls
    getok('STARTTLS') rescue return false
    return true
  end
 
  def quit
    begin
      getok('QUIT')
    rescue EOFError
    end
  end
end

Copie o arquivo smtp_tls.rb para o diretório lib do seu projeto Ruby on Rails.

Carregando a lib smtp_tls.rb no environment.rb

Volte para o environment.rb e adicione para carregar a lib smtp_tls.rb:

1
2
3
4
5
...
require 'smtp_tls'
 
Rails::Initializer.run do |config|
...

Pronto! Fazendo isso você irá conseguir enviar e-mails usando o Google Apps ou Gmail.

Existe um detalhe a ser considerado na lib smtp_tls.rb, se você olhar o código vai encontrar as linhas abaixo:

7
8
9
10
...
    #check_auth_args user, secret, authtype if user or secret
    check_auth_args user, secret
...

O código por padrão tinha a linha check_auth_args user, secret, authtype if user or secret, mas quando essa linha está habilitado os e-mails não são enviados, você pode entender melhor o por que lendo aqui: http://blog.inspired.no/smtp-error-while-using-gmail-in-rails-271. Desta forma eu deixei apenas check_auth_args user, secret.

Se você precisa entender o básico de como criar um e-mail e enviar leia aqui: http://guides.rubyonrails.org/action_mailer_basics.html.

Se você gostou desse texto e acha que ajudou você, me recomende: Recommend Me.

  • Share/Bookmark

Lab Go2Images resize e crop de imagens no formato gif, png ou jpg

Postado em 19 mai 2009
Categoria(s) Lab, PHP

Frequentemente em muitos projetos PHP é necessário trabalhar com o upload de imagens, geralmente nos formatos gif, png ou jpg.

Em muitas aplicações sempre é necessário fazer o resize e o crop das imagens, para obter um melhor resultado na visualização das imagens juntamente com o conteúdo.

Pensando nisso recentemente eu criei um projeto, chamado Go2Images, no meu laboratório, com o objetivo de realizar as funcionalidades acima.

Go2Images

O código fonte está disponível no github: http://github.com/patrickespake/go2images/tree/master e você pode testar no endereço: http://lab.patrickespake.com/go2images/.

O Go2Images foi desenvolvido usando a linguagem de programação PHP e o padrão de projeto MVC, que foi implementado do zero. Além disso ele usa a biblioteca GD para realizar as operações de resize e crop.

Você pode definir os tamanhos que as imagens devem ser redimensionadas, cadastrando a largura e altura, os sistema verifica todos os tipos de tamanhos cadastrados e usa essas informações para efetuar o resize e crop da imagens, conforme: http://lab.patrickespake.com/go2images/?controller=imageType&action=list e imagem abaixo:

Go2Images Image Type

Desta forma é possível inserir novas dimensões facilmente.

Com as dimensões de redimensionamento definidas, é possível efetuar o upload de uma imagem em: http://lab.patrickespake.com/go2images/index.php?controller=image&action=new.

Go2Images Nova Imagem

Automaticamente o sistema irá fazer o resize e crop das imagens, baseado nas informações de tamanho cadastradas http://lab.patrickespake.com/go2images/index.php?controller=image&action=show&id=1.

Go2Images Detalhes da Imagem

Primeiro o sistema efetua o resize da imagem tentando chegar o mais perto das dimensões desejadas e depois efetua o crop para deixar a imagem exatamente no tamanho informado.

No diretório public/images/system são armazenadas as imagens, é criado um diretório para cada imagem cadastrada, e dentro de cada diretório os tamanhos das imagens, sempre é armazenada a imagem original para futuros redimensionamentos.

Esse projeto é apenas um protótipo, sinta-se livre para usar, copiar e modificar.

  • Share/Bookmark

Ruby on Rails como usar outro layout para uma action

Postado em 12 mar 2009
Categoria(s) Ruby on Rails

Para usar outro layout em uma action específica em Ruby on Rails, é possível fazer o seguinte:

1
2
3
def index
  render :layout => "admin_login"
end

Onde “admin_login” é o layout que você deseja usar.

Se você gostou desse texto e acha que ajudou você, me recomende: Recommend Me.

  • Share/Bookmark

Ruby on Rails 2.2 Como Criar Rss Feed

Postado em 07 fev 2009
Categoria(s) Ruby on Rails

Hoje vou mostrar como criar Rss Feed no Ruby on Rails 2.2, no final você vai dar risada, de tão simples que é. Vamos lá!

Geralmente a action index é responsável por fazer a listagem das informações, ela pode ser parecer com isso:

1
2
3
def index
  @histories = History.find :all, :limit => 10
end

ou como abaixo, quando você está usando o plugin will_paginate:

1
2
3
def index
  @histories = History.paginate :all, :page => params[:page]
end

Não vamos precisar mexer em nada na action index.

Você precisa criar um novo template chamado index.rss.builder, que deve estar localizado em app/views/histories/index.rss.builder com o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
xml.instruct! 'xml', :version => "1.0"
xml.rss :version => "2.0" do
  xml.channel do
    xml.title "Notícias"
    xml.description "Últimas Notícias"
    xml.language('pt-BR')
    xml.link formatted_histories_url(:rss)
 
    for history in @histories
      xml.item do
        xml.title history.title
        xml.description history.content
        xml.pubDate history.created_at.to_s(:rfc822)
        xml.link history_url(history)
        xml.guid history_url(history)
      end
    end
  end
end

Pronto! O que você não acredita que está pronto? É verdade falta adicionar o link no template index.html.erb para ver o Rss Feed.

No template index.html.erb adicione:

1
<%= link_to " RSS Feed", formatted_histories_url(:rss) %>

Para acessar o Rss Feed visite: http://localhost:3000/histories.rss.

Não esqueça de definir no seu arquivo config/routes.rb que o model history trabalha com urls RESTful:

1
map.resources :histories

Uhmm! Não estou feliz ainda, acho que dá para melhorar mais, é verdade podemos adicionar:

1
	<link href="http://localhost:3000/histories.rss" rel="alternate" title="RSS" type="application/rss+xml" />

Entre as tags:

1
<head>...</head>

do HTML, fazendo isso o navegador adiciona o ícone de Feed na barra de endereço e deixa a coisa mais intuitiva para o usuário.

Vamos fazer isso de uma forma mais elegante e dinâmica.

No layout da sua aplicação adicionei yield :auto_discovery entre as tags head do HTML:

1
2
3
4
5
<head>
...
  <%= yield :auto_discovery %>
...
</head>

Agora no template index.html.erb adicione:

1
2
3
<% content_for :auto_discovery do %>
  <%= auto_discovery_link_tag(:rss, :action => :index, :format => :rss) %>
<% end %>

Agora sim ficou legal! ;-)

Mais informações assista aqui: http://media.railscasts.com/videos/087_generating_rss.mov.

Se você gostou desse texto e acha que ajudou você, me recomende: Recommend Me.

  • Share/Bookmark

Ruby on Rails como usar calendar_helper plano para eventos ou filtros

Postado em 29 jan 2009
Categoria(s) Ruby on Rails
Usando o plugin calendar_helper no Ruby on Rails

Usando o plugin calendar_helper no Ruby on Rails

O calendar_helper é um helper que permite criar calendários planos em HTML.

Eu estou usando ele para exibir todos os eventos cadastrados e permitir que o usuário veja todos os eventos de um determinado mês e os eventos num determinado dia.

Esse helper pode ser encontrado no github: http://github.com/topfunky/calendar_helper/tree/master.

Instalação:

No diretório do projeto:

1
ruby script/plugin install git://github.com/topfunky/calendar_helper.git

Agora adicione os css do calendar_helper na sua pasta public, digite no diretório do projeto:

1
ruby script/generate calendar_styles

Como usar:

Adicione o css do calendar_helper no seu layout:

1
<%= stylesheet_link_tag "calendar/grey/style" %>

Por exemplo, na action index adicione o seguinte conteúdo:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def index
  if params[:month] and params[:year]
    @year = params[:year].to_i
    @month = params[:month].to_i
 
    first = Date.civil(@year, @month, 1)
    last = Date.civil(@year, @month, -1)
 
    @events = Event.paginate :all,
      :conditions => ["(start_date BETWEEN ? AND ?) OR (end_date BETWEEN ? AND ?)", first.to_datetime, last.to_datetime, first.to_datetime, last.to_datetime],
      :page => params[:page]
 
    calendar
  end
end
 
private
 
def calendar
  @list_events_days = events_days(@events)
 
  @next_month = @month
  @next_year  = @year
 
  @previous_month = @month
  @previous_year  = @year
 
  if @month == 12
    @next_month = 1
    @next_year += 1
  else
    @next_month += 1
  end
 
  if @month == 1
    @previous_month = 12
    @previous_year -= 1
  else
    @previous_month -= 1
  end
end
 
def events_days(events)
  list_events_days = []
  events.each do |e|
    start_date = e.start_date.to_date
    end_date = e.end_date.to_date
 
    range = start_date..end_date
    range.each do |d|
      list_events_days << d
    end
  end
 
  return list_events_days
end

O código acima busca todos os eventos cadastrados, define o mês e ano para ser exibido no calendário, também cria a navegação para o próximo mês e o mês anterior.

O método calendar fica responsável por inicializar essas variáveis e fazer algumas verificações para montar corretamente as datas para navegação no calendário.

Já o método events_days é responsável por gerar um array que irá definir uma classe css para estilizar o calendário nos dias que haverá eventos.

Vamos exibir o calendário no template index.html.erb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%= calendar(
  {
    :year => @year,
    :month => @month,
    :previous_month_text => link_to(
      image_tag("icons/previous.png"),
      :action => 'index',
      :month => @previous_month,
      :year => @previous_year),
    :next_month_text => link_to(
      image_tag("icons/next.png"),
      :action => 'index',
      :month => @next_month,
      :year => @next_year)
}) do |d|
  if @list_events_days.include?(d.to_date)
    [link_to(d.mday, :action => 'day', :date => d.to_date), { :class => "specialDay" }]
  end
end
%>

No calendar_helper é obrigatório fornecer os atributos :year e :month, os demais são opcionais.

Com os atributos :previous_month_text e :next_month_text é possível definir um link para o próximo mês e mês anterior, desta forma é possível definir a navegação no calendário.

No final do helper temos:

1
2
3
4
5
...}) do |d|
    if @list_events_days.include?(d.to_date)
      [link_to(d.mday, :action => 'day', :date => d.to_date), { :class => "specialDay" }]
    end
  end

Nessa parte que eu adiciono uma classe css para marcar os dias que tem eventos no calendário, também crio um link para fazer uma navegação de eventos por dia.

Minha action day, para buscar os eventos de um determinado dia ficou assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def day
  if params[:date]
    @date = params[:date].to_date
    @year = @date.year
    @month = @date.month
 
    @events = Event.paginate :all,
      :conditions => ["(start_date <= ? and end_date >= ?) OR (start_date BETWEEN ? AND ?) OR (end_date BETWEEN ? AND ?)", @date, @date, "#{@date} 00:00:00", "#{@date} 23:59:59", "#{@date} 00:00:00", "#{@date} 23:59:59"],
      :page => params[:page]
 
    calendar
 
    first = Date.civil(@year, @month, 1)
    last = Date.civil(@year, @month, -1)
 
    events_month = Event.paginate :all,
      :conditions => ["(start_date BETWEEN ? AND ?) OR (end_date BETWEEN ? AND ?)", first.to_datetime, last.to_datetime, first.to_datetime, last.to_datetime],
      :page => params[:page]
 
    @list_events_days = events_days(events_month)
  end
end

Essa action ficou um pouco mais complexa, nela eu tenho que pegar os eventos em um determinado dia, mas também tenho que buscar todos os eventos no mês, assim consigo deixar todos os dias marcados corretamente no calendário.

Se você gostou desse texto e acha que ajudou você, me recomende: Recommend Me.

  • Share/Bookmark