Halaman

Rabu, 20 Januari 2010

[shared] Using content_for from controller

biasanya content_for digunakan untuk passing suatu blok text dr view ke layout, contohnya

layout/application.html.erb

# ...
<div class="menu">
<%= yield :menu %>
</div>
<div class="content">
<%= yield %>
</div>
# ...


homepages/show.html.erb

# ...
<% content_for :menu, generate_menu %>
# ...


nah, terkadang dibutuhkan content_for yg dapat dipanggil di controller. misalkan untuk mengurangi pengulangan dengan menggunakan before_filter (dapat jg menggunakan nested layout, akan saia bahas di post lain).
untuk itu setelah saia coba ternyata hal tersebut dapat diselesaikan dengan mudah, hanya dengan mengisi instance variable dengan nama @content_for_#{nama} dengan contoh diatas berarti:

homepages_controller.rb

# ...
@content_for_menu = generate_menu
# ...


Warning: cara tersebut sudah dicoba di rails 2.3.3 tapi ada kmungkinan deprecated untuk versi rails yang lebih baru.. kalo ada cara yg lebih baik tolong kasi tau saia via comment, thanks ^_^

Jumat, 15 Januari 2010

[shared] Simple scheduled emails using rufus-scheduler

Baru2 ini di project yg sedang saia kerjakan, saia diminta untuk mengimplementasikan automated email. Intinya mengirim email secara otomatis pada saat user melakukan sesuatu. Sekilas biasa saja, hanya menggunakan ActionMailer untuk mengirim email pada event tertentu, namun masalahnya ada beberapa email yang dikirim bukan pada saat event dijalankan, ada delay waktu bbrp hari sebelum email dikirim.

Untuk itu saia memutuskan untuk membuat mailer yang dapat dijadwalkan, selain dapat mengirimkan email pada tanggal dan waktu tertentu, email jg dikirimkan secara berkala pada jangka waktu yg ditentukan (asumsi saia akan dibutuhkan nantinya untuk email laporan berkala.)

Buat Scheduler

Pertama, install rufus-scheduler

gem install rufus-scheduler

lalu dalam folder config/initializers buat file ruby baru, misal "task_scheduler.rb"

scheduler = Rufus::Scheduler.start_new

scheduler.every("10m") do
QueuedEmail.deliver_all
end

yang akan menjalankan deliver_all pada model QueuedEmail setiap 10 menit.

Buat Model utk menyimpan jadwal

generate model baru, misal queued_email
migration:

class CreateQueuedEmails < ActiveRecord::Migration
def self.up
create_table :queued_emails do |t|
t.string :from, :limit => 100
t.string :recipients, :limit => 100
t.string :subject, :limit => 100
t.text :content
t.integer :duration
t.datetime :send_at
t.datetime :last_sent_at
t.timestamps
end
end

def self.down
drop_table :queued_emails
end
end

model:

class QueuedEmail < ActiveRecord::Base
validates_presence_of :from
validates_length_of :from, :within => 6..100

validates_presence_of :recipients
validates_length_of :recipients, :within => 6..100

def recurring?
!self.duration.blank?
end

def deliver!
puts "Sending email: #{self.inspect}"
UserMailer.deliver_custom_mail self.attributes
if recurring?
puts "set sent at: #{Time.now.utc}"
self.update_attribute :last_sent_at, Time.now.utc
else
puts "destroy"
self.destroy
end
end

def self.deliver_all
mails = self.all :conditions => ["(send_at <= :current_time) AND (duration IS NULL OR duration = \"\" OR last_sent_at IS NULL OR TIME_TO_SEC(TIMEDIFF(:current_time, last_sent_at)) >= duration)", {:current_time => Time.now.utc}]
mails.each do |mail|
mail.deliver!
end
end
end

cara kerja:
- duration: bila diisi, setelah email dikirim, email tidak akan langsung dihapus, tetapi akan dikirimkan kembali setiap duration detik
- send_at: menentukan tanggal dan waktu email akan dikirim atau dikirim pertama kalinya bila duration ditentukan.
- last_sent_at: tidak perlu diisi, digunakan secara internal untuk email berkala
- lainnya: rasanya sudah cukup jelas, sama seperti actionmailer

Tambahkan custom_mail di mailer 

Saia menggunakan UserMailer < ActionMailer::Base untuk mengirimkan email, tambahkan kode berikut di dalamnya:

def custom_mail(options)
@recipients = options["recipients"]
@from = options["from"]
@subject = options["subject"]
@sent_on = Time.now
@body[:content] = options["content"]
end

dan buat custom_mail.erb di viewnya:

<%= @content %>


Contoh penggunaan

Misalkan untuk mengirimkan survey email 2 hari setelah user register. Tambahkan kode berikut di users_controller create:

# ....
# bila registrasi sukses daftarkan email untuk dikirim setelah 2 hari
QueuedEmail.create(
:send_at => 2.days.since(Time.now.utc),
:from => "\"Site Keren\" ",
:recipients => "#{@user.email}",
:subject => "Survey supaya keren" ,
:content => "Halo #{@user.name}, isi survey berikut supaya kamu makin keren gitu loh ....."
)
# ....

untuk email berkala, tentukan duration dalam detik, misal email yg dikirim tiap hari

:duration => 24.hours


Dan segitu saja, mungkin bukan implementasi yg terbaik, tp paling tidak bisa digunakan hehe..

Kamis, 14 Januari 2010

Hello World!!!

Hello World | Halo Dunia