public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/council-webapp:master commit in: site/config/environments/, site/spec/support/, site/db/, ...
@ 2011-06-10 16:46 Petteri Räty
  0 siblings, 0 replies; only message in thread
From: Petteri Räty @ 2011-06-10 16:46 UTC (permalink / raw
  To: gentoo-commits

commit:     a79293f652cedf63f9f3cd88107e98b9b4da99f3
Author:     Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Mon Jun  6 18:50:58 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri Jun 10 16:11:42 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=a79293f6

Send email reminders about meetings using delayed_job

---
 site/Gemfile                                    |    2 +
 site/Gemfile.lock                               |    8 ++++
 site/app/mailers/user_mailer.rb                 |    6 +++
 site/app/models/agenda.rb                       |   43 +++++++++++++++++++++--
 site/app/views/user_mailer/meeting_reminder.erb |    5 +++
 site/config/environments/test.rb                |    2 +
 site/config/initializers/custom_configs.rb      |    4 ++-
 site/db/schema.rb                               |   21 ++++++++++-
 site/doc/sample_configs/reminders.yml           |    1 +
 site/script/delayed_job                         |    5 +++
 site/spec/models/agenda_spec.rb                 |   41 +++++++++++++++++++++
 site/spec/models/user_mailer_spec.rb            |   14 +++++++
 site/spec/spec_helper.rb                        |    5 +++
 site/spec/support/delayed_should_receive.rb     |   11 ++++++
 site/spec/support/should_have_text.rb           |    8 ++++
 15 files changed, 170 insertions(+), 6 deletions(-)

diff --git a/site/Gemfile b/site/Gemfile
index fa841ac..a95faa0 100644
--- a/site/Gemfile
+++ b/site/Gemfile
@@ -3,11 +3,13 @@ gem 'rails', '3.0.3'
 gem 'sqlite3-ruby', :require => 'sqlite3'
 gem 'devise'
 gem 'hobo_devise', '>=0.0.2'
+gem 'delayed_job'
 
 group :development, :test do
   gem 'ruby-debug'
   gem 'rspec-rails'
   gem 'shoulda'
+  gem 'email_spec'
 
   gem 'cucumber-rails'
   gem 'capybara'

diff --git a/site/Gemfile.lock b/site/Gemfile.lock
index 4313a4a..aca3ead 100644
--- a/site/Gemfile.lock
+++ b/site/Gemfile.lock
@@ -57,7 +57,11 @@ GEM
       nokogiri (>= 1.4.4)
       rack-test (>= 0.5.7)
     culerity (0.2.15)
+    daemons (1.1.0)
     database_cleaner (0.6.6)
+    delayed_job (2.1.2)
+      activesupport (~> 3.0)
+      daemons
     devise (1.3.4)
       bcrypt-ruby (~> 2.1.2)
       orm_adapter (~> 0.0.3)
@@ -69,6 +73,8 @@ GEM
     dryml (1.3.0.pre28)
       actionpack (>= 3.0.0)
       hobo_support (= 1.3.0.pre28)
+    email_spec (1.1.1)
+      rspec (~> 2.0)
     erubis (2.6.6)
       abstract (>= 1.0.0)
     factory_girl (1.3.3)
@@ -207,7 +213,9 @@ DEPENDENCIES
   capybara
   cucumber-rails
   database_cleaner
+  delayed_job
   devise
+  email_spec
   factory_girl
   fuubar-cucumber
   hobo (>= 1.3.0.pre28)

diff --git a/site/app/mailers/user_mailer.rb b/site/app/mailers/user_mailer.rb
index c5c18f8..d9515f3 100644
--- a/site/app/mailers/user_mailer.rb
+++ b/site/app/mailers/user_mailer.rb
@@ -7,4 +7,10 @@ class UserMailer < ActionMailer::Base
           :to      => user.email )
   end
 
+  def meeting_reminder(user, agenda)
+    @user = user
+    @agenda = agenda
+    mail(:subject => "Upcoming meeting reminder - #{agenda.meeting_time.to_s}",
+          :to => user.email)
+  end
 end

diff --git a/site/app/models/agenda.rb b/site/app/models/agenda.rb
index 22414d7..ea58041 100644
--- a/site/app/models/agenda.rb
+++ b/site/app/models/agenda.rb
@@ -3,7 +3,8 @@ class Agenda < ActiveRecord::Base
   hobo_model # Don't put anything above this
 
   fields do
-    meeting_time  :datetime
+    meeting_time        :datetime
+    email_reminder_sent :boolean, :null => false, :default => false
     timestamps
   end
 
@@ -101,7 +102,12 @@ class Agenda < ActiveRecord::Base
     end
   end
 
-  def self.voters
+  def time_for_reminders
+    offset = CustomConfig['Reminders']['hours_before_meeting_to_send_email_reminders'].hours
+    meeting_time - offset
+  end
+
+  def self.voters_users
     # It's possible to rewrite this as SQL, but
     #  * this method is rarely called
     #  * it fetches little data
@@ -109,7 +115,38 @@ class Agenda < ActiveRecord::Base
     # Joachim
     council = ::User.council_member_is(true)
     proxies = Agenda.current.proxies
-    [council - proxies.*.council_member + proxies.*.proxy].flatten.*.irc_nick
+    [council - proxies.*.council_member + proxies.*.proxy].flatten
+  end
+
+  def self.voters
+    Agenda.voters_users.*.irc_nick
+  end
+
+  def self.send_current_agenda_reminders
+    agenda = Agenda.current
+
+    return if agenda.email_reminder_sent?
+    return if Time.now < agenda.time_for_reminders
+
+    for user in Agenda.voters_users
+      UserMailer.delay.deliver_meeting_reminder(user, agenda)
+    end
+
+    agenda.email_reminder_sent = true
+    agenda.save!
+  end
+
+  before_save do |a|
+    return true if a.new_record?
+    return true unless a.meeting_time_changed?
+    a.email_reminder_sent = false
+    true
+  end
+
+  after_save do |a|
+    if a.new_record? or a.meeting_time_changed?
+      Agenda.delay(:run_at => a.time_for_reminders).send_current_agenda_reminders
+    end
   end
 
   protected

diff --git a/site/app/views/user_mailer/meeting_reminder.erb b/site/app/views/user_mailer/meeting_reminder.erb
new file mode 100644
index 0000000..b49e7e6
--- /dev/null
+++ b/site/app/views/user_mailer/meeting_reminder.erb
@@ -0,0 +1,5 @@
+<%= @user %>,
+
+meeting will take place on <%= @agenda.meeting_time.to_s %>. You can view agenda for the meeting on:
+
+  <%= agenda_url(@agenda) %>

diff --git a/site/config/environments/test.rb b/site/config/environments/test.rb
index c2fc237..944a63f 100644
--- a/site/config/environments/test.rb
+++ b/site/config/environments/test.rb
@@ -32,4 +32,6 @@ Council::Application.configure do
 
   # Print deprecation notices to the stderr
   config.active_support.deprecation = :stderr
+
+  config.action_mailer.default_url_options = { :host => 'localhost', :port => '3000' }
 end

diff --git a/site/config/initializers/custom_configs.rb b/site/config/initializers/custom_configs.rb
index 599646f..dca866f 100644
--- a/site/config/initializers/custom_configs.rb
+++ b/site/config/initializers/custom_configs.rb
@@ -1,2 +1,4 @@
 CustomConfig = {}
-CustomConfig['Bot'] = YAML.load open('config/bot.yml').read
+for conf in ['bot', 'reminders']
+  CustomConfig[conf.camelize] = YAML.load open("config/#{conf}.yml").read
+end

diff --git a/site/db/schema.rb b/site/db/schema.rb
index fec65de..071ff84 100644
--- a/site/db/schema.rb
+++ b/site/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20110603133359) do
+ActiveRecord::Schema.define(:version => 20110606170332) do
 
   create_table "agenda_items", :force => true do |t|
     t.string   "title"
@@ -30,12 +30,29 @@ ActiveRecord::Schema.define(:version => 20110603133359) do
     t.datetime "meeting_time"
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.string   "state",         :default => "open"
+    t.string   "state",               :default => "open"
     t.datetime "key_timestamp"
+    t.boolean  "email_reminder_sent", :default => false,  :null => false
   end
 
   add_index "agendas", ["state"], :name => "index_agendas_on_state"
 
+  create_table "delayed_jobs", :force => true do |t|
+    t.integer  "priority",   :default => 0
+    t.integer  "attempts",   :default => 0
+    t.text     "handler"
+    t.text     "last_error"
+    t.datetime "run_at"
+    t.datetime "locked_at"
+    t.datetime "failed_at"
+    t.string   "locked_by"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "delayed_jobs", ["locked_by"], :name => "delayed_jobs_locked_by"
+  add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
+
   create_table "participations", :force => true do |t|
     t.string   "irc_nick"
     t.datetime "created_at"

diff --git a/site/doc/sample_configs/reminders.yml b/site/doc/sample_configs/reminders.yml
new file mode 100644
index 0000000..edf937a
--- /dev/null
+++ b/site/doc/sample_configs/reminders.yml
@@ -0,0 +1 @@
+hours_before_meeting_to_send_email_reminders: 24

diff --git a/site/script/delayed_job b/site/script/delayed_job
new file mode 100755
index 0000000..edf1959
--- /dev/null
+++ b/site/script/delayed_job
@@ -0,0 +1,5 @@
+#!/usr/bin/env ruby
+
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
+require 'delayed/command'
+Delayed::Command.new(ARGV).daemonize

diff --git a/site/spec/models/agenda_spec.rb b/site/spec/models/agenda_spec.rb
index 2a08210..83b31a3 100644
--- a/site/spec/models/agenda_spec.rb
+++ b/site/spec/models/agenda_spec.rb
@@ -147,4 +147,45 @@ describe Agenda do
     (voters - nicks).should be_empty
     (nicks - voters).should be_empty
   end
+
+  it 'should add Agenda.send_current_agenda_reminders to delayed jobs when created' do
+    Agenda.should_receive_delayed(:send_current_agenda_reminders)
+    Factory(:agenda)
+  end
+
+  it 'should add Agenda.send_current_agenda_reminders to delayed jobs when meeting time changes' do
+    a = Factory(:agenda)
+    Agenda.should_receive_delayed(:send_current_agenda_reminders)
+    a.meeting_time = Time.now + 24.hours
+    a.save!
+  end
+
+  it 'should set email_reminder_sent to false when time changes' do
+    a = Factory(:agenda, :email_reminder_sent => true)
+    lambda {
+    a.meeting_time = Time.now + 24.hours
+    a.save!
+    }.should change(a, :email_reminder_sent?).from(true).to(false)
+  end
+
+  it 'should send reminders properly with send_current_agenda_reminders using delayed jobs' do
+    agenda = Factory(:agenda)
+    users = users_factory([:user] * 2)
+    council = users_factory([:council] * 2)
+    Factory(:proxy, :proxy => users.first, :council_member => council.first, :agenda => agenda)
+    UserMailer.should_receive_delayed(:deliver_meeting_reminder, council.last, agenda)
+    UserMailer.should_receive_delayed(:deliver_meeting_reminder, users.first, agenda)
+
+    Agenda.send_current_agenda_reminders
+
+    agenda.reload
+    agenda.email_reminder_sent.should be_true
+  end
+
+  it 'should not send reminders with send_current_agenda_reminders if Agenda.current.email_reminder_sent is true' do
+    a = Factory(:agenda, :email_reminder_sent => true)
+    users = users_factory([:user] * 2)
+    UserMailer.should_not_receive(:delay)
+    Agenda.send_current_agenda_reminders
+  end
 end

diff --git a/site/spec/models/user_mailer_spec.rb b/site/spec/models/user_mailer_spec.rb
new file mode 100644
index 0000000..ea2c2bc
--- /dev/null
+++ b/site/spec/models/user_mailer_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+describe UserMailer do
+  it 'should send proper meeting reminders' do
+    user = Factory(:user)
+    agenda = Factory(:agenda)
+    reminder = UserMailer.meeting_reminder(user, agenda)
+    reminder.should deliver_to(user.email)
+    reminder.should deliver_from("no-reply@localhost")
+    reminder.should have_text(/meeting will take place on #{agenda.meeting_time.to_s}./)
+    reminder.should have_text(/You can view agenda for the meeting on:/)
+    reminder.should have_text(/http:\/\/localhost:3000\/agendas\/#{agenda.id}/)
+    reminder.should have_subject("Upcoming meeting reminder - #{agenda.meeting_time.to_s}")
+  end
+end

diff --git a/site/spec/spec_helper.rb b/site/spec/spec_helper.rb
index a8b8aea..47ed37e 100644
--- a/site/spec/spec_helper.rb
+++ b/site/spec/spec_helper.rb
@@ -15,3 +15,8 @@ RSpec.configure do |config|
   config.mock_with :rspec
   config.use_transactional_fixtures = true
 end
+
+RSpec.configure do |config|
+  config.include(EmailSpec::Helpers)
+  config.include(EmailSpec::Matchers)
+end

diff --git a/site/spec/support/delayed_should_receive.rb b/site/spec/support/delayed_should_receive.rb
new file mode 100644
index 0000000..0fbbe27
--- /dev/null
+++ b/site/spec/support/delayed_should_receive.rb
@@ -0,0 +1,11 @@
+class Object
+  def should_receive_delayed(method, *args)
+    m = RSpec::Mocks::Mock.new('proxy')
+    if args.empty?
+      m.should_receive(method)
+    else
+      m.should_receive(method).with(*args)
+    end
+    self.should_receive(:delay).and_return(m)
+  end
+end

diff --git a/site/spec/support/should_have_text.rb b/site/spec/support/should_have_text.rb
new file mode 100644
index 0000000..3016c13
--- /dev/null
+++ b/site/spec/support/should_have_text.rb
@@ -0,0 +1,8 @@
+module Mail
+  class Message
+    # emailspec doesn't add this, so we have to
+    def has_text?(text)
+      not body.to_s.match(text).nil?
+    end
+  end
+end



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2011-06-10 16:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-10 16:46 [gentoo-commits] proj/council-webapp:master commit in: site/config/environments/, site/spec/support/, site/db/, Petteri Räty

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox