Criando eventos recorrentes com Recurrence
Leia em 2 minutos
Recurrence é uma biblioteca criada para gerar eventos recorrentes de maneira simples. Eu criei essa gem há tempos, mas nunca escrevi nada sobre ela. Eis que muitas pessoas começaram a me mandar e-mails perguntando como utilizá-la e chegou a hora de fazer um artigo mostrando seu uso na prática.
A primeira coisa que você precisa fazer é instalar a gem.
sudo gem install recurrence
Depois, basta adicionar à biblioteca.
require "rubygems"
require "recurrence"
A maneira mais simples de usar é instanciar um objeto através dos métodos de classe daily
, weekly
, monthly
e yearly
, que permitem criar eventos diários, semanais, mensais e anuais, respectivamente.
r = Recurrence.daily
Para retornar a próxima data, você deve utilizar o método Recurrence#next
.
r.next
#=> Fri, 18 Dec 2009
r.next
#=> Fri, 18 Dec 2009
Você também pode utilizar o método Recurrence#next!
, que altera a variável interna de data, como mostra o exemplo abaixo.
r.next!
#=> Fri, 18 Dec 2009
r.next!
#=> Sat, 19 Dec 2009
Se você quiser, pode especificar o intervalo de dias que o evento pode se repetir; basta utilizar a opção :starts
e :ends
.
# define the starting date to 2009-12-24
r = Recurrence.daily(:starts => Date.new(2009, 12, 24))
# define the ending date to 2009-12-31
r = Recurrence.daily(:ends => Date.new(2009, 12, 31))
Você também pode passar essas datas como strings, desde que elas sejam interpretadas pelo método Date#parse
.
r = Recurrence.daily(:starts => "2009-12-24")
Os atalhos são uma excelente maneira de tornar o código mais semântico, mas em alguns casos é melhor seguir com o bom e velho método new
.
r = Recurrence.new(:every => :week, :on => :saturday, :interval => 2)
Como você pode ver no exemplo acima, estamos criando um evento semanal, que acontece aos sábados, a cada duas semanas. Ao utilizar o método Recurrence#next! você terá algo como isso:
r.next!
#=> Sat, 19 Dec 2009
r.next!
#=> Sat, 02 Jan 2010
Você também pode especificar uma lista com os dias da semana que o evento deve ocorrer.
r = Recurrence.weekly(:on => [:saturday, :sunday])
r.next!
#=> Sat, 19 Dec 2009
r.next!
#=> Sun, 20 Dec 2009
r.next!
#=> Sat, 26 Dec 2009
Para acessar uma lista com todos os eventos disponíveis, basta utilizar o método Recurrence#events
.
r.events
#=> [Sun, 20 Dec 2009, Sun, 27 Dec 2009]
Esse método fará irá guardar a lista de datas geradas, aumentando a performance se ele for acessado mais de uma vez. Se você quiser regerar essas datas, pode utilizar o método Recurrence#events!
.
Também é possível verificar se uma data está no intervalo especificado no objeto Recurrence
.
r = Recurrence.weekly(:on => :saturday)
r.include? "2009-12-19"
#=> true
Como usar na prática
Como você pode ver, o Recurrence é totalmente parametrizado. Essa abordagem permite que você armazene os itens necessários para montar sua recorrência em um banco de dados, por exemplo. Digamos que você tenha um modelo Event
, com o seguinte schema:
class CreateEvents < ActiveRecord::Migration
def self.up
create_table :events do |t|
t.string :title, :null => false
t.binary :meta, :null => false
t.date :scheduled_to, :null => false
end
end
end
Os atributos que serão utilizados no Recurrence são :meta
e :scheduled_to
. O primeiro irá armazenar o tipo de recorrência e as informações como dia, intervalo, etc. Já o segundo, irá armazenar a próxima data do evento, para diminuir a geração de datas. O modelo Event
pode armazenar os atributos como este exemplo:
class Event < ActiveRecord::Base
serialize :meta, Hash
validates_presence_of :meta, :title, :scheduled_to
end
Veja um exemplo de como cadastrar um evento “Pagamento”, que acontece todo mês no dia 5.
options = {:every => :month, :on => 5}
r = Recurrence.new(options)
event = Event.new(:title => "Pagamento", :meta => options, :scheduled_to => r.next)
event.save!
Na hora de montar o objeto de recorrência, você pode utilizar algo como isto:
event = Event.first
r = Recurrence.new(event.meta.merge(:starts => event.scheduled_to))
r.next
#=> Tue, 05 Jan 2010
Se você precisar exibir um evento mais de uma vez, utilize este mesmo processo e exiba os eventos com o método events
.
Finalizando
Criar eventos recorrentes nem sempre é uma tarefa simples, principalmente no que diz respeito à performance. O José Valim fez uma série de contribuições que ajudaram a melhor esse ponto, além de outras funcionalidades como os atalhos.
Para conhecer mais sobre as opções disponíveis do Recurrence, acesse o README do projeto no Github.