Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions app/controllers/concerns/invitation_controller_concerns.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module InvitationControllerConcerns
extend ActiveSupport::Concern

included do
before_action :set_invitation

include InstanceMethods
end

module InstanceMethods

def accept
if @invitation.attending.eql? true
redirect_to root_path, notice: t("messages.already_rsvped")

elsif has_remaining_seats?(@invitation)
@invitation.update_attribute(:attending, true)

redirect_to root_path, notice: t("messages.accepted_invitation",
name: @invitation.member.name)
else
redirect_to root_path, notice: t("messages.no_available_seats")
end
end

def reject
if @invitation.attending.eql? false
redirect_to root_path, notice: t("messages.not_attending_already")
else
@invitation.update_attribute(:attending, false)
redirect_to root_path, notice: t("messages.rejected_invitation", name: @invitation.member.name)
end
end
end
end
17 changes: 3 additions & 14 deletions app/controllers/course/invitation_controller.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
class Course::InvitationController < ApplicationController
include InvitationControllerConcerns

def accept
private
def set_invitation
@invitation = CourseInvitation.find_by_token(params[:id])

if @invitation.attending.eql? true
redirect_to root_path, notice: t("messages.already_rsvped")

elsif has_remaining_seats?(@invitation)
@invitation.update_attribute(:attending, true)

redirect_to root_path, notice: t("messages.accepted_invitation",
name: @invitation.member.name)
else
redirect_to root_path, notice: t("messages.no_available_seats")
end
end

private
def has_remaining_seats? invitation
invitation.course.seats > invitation.course.attending_invitations.length
end
Expand Down
17 changes: 4 additions & 13 deletions app/controllers/invitation_controller.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
class InvitationController < ApplicationController
include InvitationControllerConcerns

def accept
@invitation = SessionInvitation.find_by_token(params[:id])

if @invitation.attending.eql? true
redirect_to root_path, notice: t("messages.already_rsvped")

elsif has_remaining_seats?(@invitation)
@invitation.update_attribute(:attending, true)
private

redirect_to root_path, notice: t("messages.accepted_invitation",
name: @invitation.member.name)
else
redirect_to root_path, notice: t("messages.no_available_seats")
end
def set_invitation
@invitation = SessionInvitation.find_by_token(params[:id])
end

private
def has_remaining_seats? invitation
invitation.sessions.seats > invitation.sessions.attending_invitations.length
end
Expand Down
14 changes: 14 additions & 0 deletions app/mailers/session_invitation_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ def invite_student sessions, member, invitation
end
end

def remind_student session, member, invitation
@session = session
@member = member
@invitation = invitation

load_attachments

subject = "Reminder for #{@session.title} by Codebar - #{l(@session.date_and_time, format: :email_title)}"

mail(mail_args(member, subject)) do |format|
format.html
end
end

private

def load_attachments
Expand Down
15 changes: 15 additions & 0 deletions app/models/concerns/invitable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Invitable
extend ActiveSupport::Concern

included do
include InstanceMethods
end

module InstanceMethods

def attending_invitations
invitations.accepted
end

end
end
8 changes: 3 additions & 5 deletions app/models/course.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
class Course < ActiveRecord::Base
has_many :course_invitations
include Invitable

has_many :invitations, class_name: "CourseInvitation"
belongs_to :tutor, class_name: 'Member', foreign_key: 'tutor_id'

before_save :set_slug
Expand All @@ -9,10 +11,6 @@ class Course < ActiveRecord::Base
scope :upcoming, -> { where("date_and_time >= ?", DateTime.now).order(:date_and_time) }
scope :past, -> { where("date_and_time < ?", DateTime.now).order(:date_and_time) }

def attending_invitations
course_invitations.accepted
end

def to_param
slug
end
Expand Down
6 changes: 6 additions & 0 deletions app/models/invitation_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ def self.send_course_emails course
end
end

def self.send_session_reminders session
session.attending_invitations.map do |invitation|
invitation.send_reminder
end
end

end
8 changes: 8 additions & 0 deletions app/models/reminders.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Reminders < ActiveRecord::Base

scope :session, ->(session) { where(reminder_type: "session", reminder_id: session.id) }

def self.add_for_session session, count
Reminders.create reminder_type: "session", reminder_id: session.id, count: count
end
end
4 changes: 4 additions & 0 deletions app/models/session_invitation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ class SessionInvitation < ActiveRecord::Base
validates :sessions, :member, presence: true
validates :member_id, uniqueness: { scope: [:sessions ] }

def send_reminder
SessionInvitationMailer.remind_student(self.sessions, self.member, self).deliver if attending
end

private

def email
Expand Down
9 changes: 4 additions & 5 deletions app/models/sessions.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
class Sessions < ActiveRecord::Base
include Invitable

has_many :session_invitations
has_many :invitations, class_name: "SessionInvitation"
has_many :sponsor_sessions
has_many :sponsors, through: :sponsor_sessions

scope :upcoming, -> { where("date_and_time > ?", DateTime.now) }
scope :upcoming, -> { where("date_and_time >= ?", DateTime.now).order(:date_and_time) }
scope :next, -> { upcoming.first }

def attending_invitations
session_invitations.accepted
end
end
33 changes: 33 additions & 0 deletions app/views/session_invitation_mailer/remind_student.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<h2 style="font-weight: 400; font-size: 24px; border-bottom:1px solid #ececec; padding-bottom: 15px; margin-bottom:35px">Hi <%= @member.name %></h2>

<h3 style="font-weight: 600; font-size: 17px; letter-spacing: 0.02em; color: #111111"><%= @session.title %> <small style="color: #4c4066">by Codebar</small> is almost here!</h3>
<p style="font-weight: 300; font-size: 16px; color: #2e2e2e; margin-bottom: 50px;"> If your are unable to attend, please change your attendance status.<br></p>

<div style="display:inline-block">
<div style="width:340px; padding-right: 40px; display: inline-block; vertical-align: top;">
<h2 style="color: #2d183d; font-size: 26px; font-weight: 500;letter-spacing: 0.03em; margin-bottom: 0;"><%= @session.title %> <small style="color: #4c4066">by Codebar</small></h2>
<small><%= @session.description %></small>
<p style="font-size: 16px; font-weight: 300; margin-top: 7px;">on <b style="color: #555555;font-size: 16px; font-weight: 600; margin-top: 0;"><%= l(@session.date_and_time, format: :email)%></b></p>
<div style="background-color: #F7F7F7; width: 90%; border-radius: 6px; box-shadow: 1px 1px 0 rgba(250, 250, 250, 0.5) inset, -1px -1px 2px rgba(250, 250, 250, 0.1) inset; font-size: 18px; padding: 5px 14px; text-align: center; margin: 31px 0 25px; border: 1px solid #dddddd;">
<p> <%= link_to "I can no longer attend", full_url_for(reject_invitation_url(@invitation)), style: "text-decoration:none; color: #663095; font-size: 25px; font-weight: 600; letter-spacing: 0.02em; margin: 10px; text-decoration: none; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);"%></p>
</div>
</div>


<div style="width:150px; border-left: 1px solid #ececec; padding-left: 50px; display: inline-block;">
<h3 style="color: #434950; font-size: 17px;font-weight: 600;letter-spacing: 0.02em;">Location</h3>
<h2 style="color: #2D183D; font-weight: 400; ">Shutl</h2>
<p style="color: #434950;font-size: 16px; font-weight: 400;">
The Courtyard building<br/>
11 Curtain Road, 2nd Floor<br/>
London, EC2A 3LT<br/>
</p>
<a href="http://goo.gl/maps/nIfo6" style="color: #a369d5; text-decoration: underline" >view map</a>
<div style="width:120px; height:56px; margin-top: 33px;"><%=image_tag(attachments["shutl.png"].url, width: "120px") %></div>
</div>

</div>

<div style="clear:both; width: 100%; height: 10px;"></div>
<div style="color: #2E2E2E; font-size: 18px; font-weight: 600; margin-top: 40px;">See you on Wednesday!</div>

6 changes: 4 additions & 2 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ en:
date: "%d %B %Y"

messages:
accepted_invitation: "Thanks for getting back to us %{name}. See you at the meeting!"
already_rsvped: "You have alredy confirmed you attendance for this meeting!"
accepted_invitation: "Thanks for getting back to us %{name}. See you at the session!"
rejected_invitation: "We are so sad you can't make it, but thanks for letting us know %{name}."
already_rsvped: "You have alredy confirmed you attendance!"
not_attending_already: "You have alredy confirmed you can't make it!"
no_available_seats: "Unfortunately there are no more spaces left :(. If you would like to join our waiting list send us an email at meetings@codebar.io."
member_notifications: "You will be receiving notifications for: %{roles}"
no_roles: "You have not signed up for any notifications. If you change your mind, send us an email at meetins@codebar.io so we can change your settings"
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
resources :invitation, only: [] do
member do
get "accept"
get "reject"
end
end

namespace :course do
resources :invitation, only: [] do
member do
get "accept"
get "reject"
end
end
end
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20131104030726_create_reminders.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateReminders < ActiveRecord::Migration
def change
create_table :reminders do |t|
t.string :reminder_type
t.string :reminder_id
t.datetime :date_and_time
t.integer :count

t.timestamps
end
end
end
11 changes: 10 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20131103212835) do
ActiveRecord::Schema.define(version: 20131104030726) do

create_table "addresses", force: true do |t|
t.string "flat"
Expand Down Expand Up @@ -68,6 +68,15 @@
add_index "members_roles", ["member_id", "role_id"], name: "index_members_roles_on_member_id_and_role_id"
add_index "members_roles", ["member_id"], name: "index_members_roles_on_member_id"

create_table "reminders", force: true do |t|
t.string "reminder_type"
t.string "reminder_id"
t.datetime "date_and_time"
t.integer "count"
t.datetime "created_at"
t.datetime "updated_at"
end

create_table "roles", force: true do |t|
t.string "name"
t.string "description"
Expand Down
13 changes: 13 additions & 0 deletions lib/tasks/reminders.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace :reminders do
desc "Send out reminders"

task sessions: :environment do
Sessions.upcoming.first.tap do |session|
unless Reminders.session(session).exists?
invitations = InvitationManager.send_session_reminders(session)

Reminders.add_for_session session, invitations.length
end
end
end
end
7 changes: 7 additions & 0 deletions spec/fabricators/reminder_fabricator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Fabricator(:reminders) do
count 10
end

Fabricator(:session_reminder, from: :reminders) do
reminder_type "session"
end
4 changes: 4 additions & 0 deletions spec/fabricators/session_invitation_fabricator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
note "I'd love to attend"
sessions
end

Fabricator(:attending_session_invitation, from: :session_invitation) do
attending true
end
12 changes: 7 additions & 5 deletions spec/features/accepting_invitation_spec.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
require 'spec_helper'

feature 'a member can accept an invitation' do
feature 'a member can' do

context "session" do
context "#session" do
let(:invitation) { Fabricate(:session_invitation) }
let(:invitation_path) { accept_invitation_path(invitation) }
let(:accepting_invitation_path) { accept_invitation_path(invitation) }
let(:rejecting_invitation_path) { reject_invitation_path(invitation) }

let(:set_no_available_slots) { invitation.sessions.update_attribute(:seats, 0) }

it_behaves_like "invitation route"

end

context "course" do
context "#course" do
let(:invitation) { Fabricate(:course_invitation) }
let(:invitation_path) { accept_course_invitation_path(invitation) }
let(:accepting_invitation_path) { accept_course_invitation_path(invitation) }
let(:rejecting_invitation_path) { reject_course_invitation_path(invitation) }

let(:set_no_available_slots) { invitation.course.update_attribute(:seats, 0) }

Expand Down
16 changes: 12 additions & 4 deletions spec/mailers/session_invitation_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@
describe SessionInvitationMailer do

let(:email) { ActionMailer::Base.deliveries.last }
let(:session) { Fabricate(:sessions, title: "HTML & CSS") }
let(:member) { Fabricate(:member) }
let(:invitation) { Fabricate(:session_invitation, sessions: session, member: member) }

it "#invite_student" do
member = Fabricate(:member)
sessions = Fabricate(:sessions, title: "HTML & CSS", date_and_time: DateTime.new(2013,10,30,18,30))
invitation_token = "token"

email_subject = "HTML & CSS by Codebar - Wednesday, 30 Oct at 18:30"
SessionInvitationMailer.invite_student(sessions, member, invitation_token).deliver
email_subject = "#{session.title} by Codebar - #{I18n.l(session.date_and_time, format: :email_title)}"
SessionInvitationMailer.invite_student(session, member, invitation).deliver

expect(email.subject).to eq(email_subject)
end

it "#remind_student" do
email_subject = "Reminder for #{session.title} by Codebar - #{I18n.l(session.date_and_time, format: :email_title)}"
SessionInvitationMailer.remind_student(session, member, invitation).deliver

expect(email.subject).to eq(email_subject)
end
Expand Down
Loading