Skip to content

Commit

Permalink
added automated email notifications for people providing answers. Add…
Browse files Browse the repository at this point in the history
…ed development gems: gem to auto-populate data and gem to handle server loads on email requests. Added security layer on development login to protect user data.
  • Loading branch information
KelseyDH committed Apr 14, 2014
1 parent 132b751 commit bf7cfc9
Show file tree
Hide file tree
Showing 31 changed files with 285 additions and 16 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp

# Ignore Email Variables for security reasons
config/initializers/email_vars.rb
7 changes: 7 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ gem 'html2haml'

gem 'devise'

#if you're using MongoDB you need a different gem
gem 'delayed_job_active_record'
gem 'delayed_job_web'

gem 'faker', group: [:development, :test]

# # DEPRECRATED Use sqlite3 as the database for Active Record
# gem 'sqlite3'

Expand All @@ -23,6 +29,7 @@ group :development do
gem "awesome_print"
# gem 'better_errors' #debugging gem
# gem 'binding_of_caller' #debugging gem
# gem "letter-opener"

end

Expand Down
20 changes: 20 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.7.0)
delayed_job (4.0.1)
activesupport (>= 3.0, < 4.2)
delayed_job_active_record (4.0.1)
activerecord (>= 3.0, < 4.2)
delayed_job (>= 3.0, < 4.1)
delayed_job_web (1.2.8)
activerecord (> 3.0.0)
delayed_job (> 2.0.3)
sinatra (>= 1.4.4)
devise (3.2.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
Expand All @@ -47,6 +56,8 @@ GEM
warden (~> 1.2.3)
erubis (2.7.0)
execjs (2.0.2)
faker (1.2.0)
i18n (~> 0.5)
ffi (1.9.3-x86-mingw32)
haml (4.0.5)
tilt
Expand Down Expand Up @@ -80,6 +91,8 @@ GEM
quiet_assets (1.0.2)
railties (>= 3.1, < 5.0)
rack (1.5.2)
rack-protection (1.5.3)
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (4.0.2)
Expand Down Expand Up @@ -110,6 +123,10 @@ GEM
json (~> 1.8)
rdoc (~> 4.0, < 5.0)
sexp_processor (4.4.3)
sinatra (1.4.5)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
spoon (0.0.4)
ffi
sprockets (2.11.0)
Expand Down Expand Up @@ -143,7 +160,10 @@ PLATFORMS
DEPENDENCIES
awesome_print
bootstrap-sass (~> 3.1.1)
delayed_job_active_record
delayed_job_web
devise
faker
haml
hirb
html2haml
Expand Down
2 changes: 2 additions & 0 deletions app/assets/javascripts/favourites.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.
2 changes: 1 addition & 1 deletion app/assets/stylesheets/bootstrapoverride.css.scss
Original file line number Diff line number Diff line change
@@ -1 +1 @@
@import "bootstrap";
@import "bootstrap";
3 changes: 3 additions & 0 deletions app/assets/stylesheets/favourites.css.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Place all the styles related to the favourites controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
2 changes: 2 additions & 0 deletions app/controllers/answers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ def create
#answer_attributes is a private method taking care of NEW parameters

if @answer.save
# AnswerMailer.notify_question_owner(@answer).deliver
AnswerMailer.delay.notify_question_owner(@answer) #Note: Uses a Delay gem
redirect_to @question, notice: "Answer Submitted Successfully"
else
render "/questions/show"
Expand Down
33 changes: 33 additions & 0 deletions app/controllers/favourites_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class FavouritesController < ApplicationController

before_action :authenticate_user!
before_action :find_question

def create
@question = Question.find(params[:question_id])
@favourite = @question.favourites.new
@favourite.user = current_user
if @favourite.save
redirect_to @question, notice: "Thank you for favouriting!"
else
redirect_to @question, alert: "Could not favourite again!"
end

end

def destroy
@favourite = current_user.favourites.find(params[:id])
if @favourite.destroy
redirect_to @question, alert: "You have unfavourited!"
else
redirect_to @question, alert: "Could not unfavourite!"
end
end

private

def find_question
@question = Question.find(params[:question_id])
end

end
3 changes: 2 additions & 1 deletion app/controllers/questions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def show
@answers = @question.answers.ordered_by_creation
#Note that @answers is being used by show.html.haml to render data, which is then used to identify
#partial page _answer.html.haml
@vote = current_user.vote_for(@question) || Vote.new
#NEEDS FIXING: @vote = current_user.vote_for(@question) || Vote.new
@favourite = current_user.favourite_for(@question)
end


Expand Down
2 changes: 2 additions & 0 deletions app/helpers/favourites_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module FavouritesHelper
end
11 changes: 11 additions & 0 deletions app/mailers/answer_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class AnswerMailer < ActionMailer::Base
default from: "[email protected]"

def notify_question_owner(answer)
@answer = answer
@question = answer.question
@receiver = @question.user
mail(to: @receiver.email,
subject: "You have a new answer on your question!")
end
end
7 changes: 7 additions & 0 deletions app/models/favourite.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Favourite < ActiveRecord::Base
belongs_to :question
belongs_to :user

validates :user_id, uniqueness: {scope: :question_id}
#prevents users from favouriting any single question more than once
end
3 changes: 3 additions & 0 deletions app/models/question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class Question < ActiveRecord::Base
has_many :categorizations, dependent: :destroy
has_many :categories, through: :categorizations

has_many :favourites, dependent: :destroy
has_many :favourited_users, through: :favourites, source: :user

has_one :question_detail
# Methods for manipulating question_detail DB:
# ~> question.build_question_detail(notes: "hello")
Expand Down
12 changes: 12 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ class User < ActiveRecord::Base
has_many :questions

#Note syntax "voted_questions" is a rails convention for models
has_many :votes, dependent: :destroy
has_many :voted_questions, through: :votes, source: :questions

has_many :favourites, dependent: :destroy
has_many :favourited_questions, through: :favourites, source: :questions


# dependency to add when likes are added.
Expand All @@ -23,6 +26,15 @@ def vote_for(question)
Vote.where(question: question, user: self).first
end

def favourite_for(question)
favourites.where(question: question).first
end

##Method below is same as above, but a useful method with slightly different uses
# def has_favorited?(question)
# favourited_questions.include? question
# end

def full_name
if first_name || last_name
"#{first_name} #{last_name}".squeeze(" ").strip
Expand Down
11 changes: 11 additions & 0 deletions app/views/answer_mailer/notify_question_owner.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Hello #{@receiver.full_name},

You have an answer for your question:

Question: #{@question.title}

Answer: #{@answer.body}

Regards,

Customer Service Team
11 changes: 11 additions & 0 deletions app/views/answer_mailer/notify_question_owner.text.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
%p Hello #{@receiver.full_name},
%br
%p You have an answer for your question:
%br
%p Question: #{@question.title}
%br
%p Answer: #{@answer.body}
%br
%p Regards,
%br
%p Customer Service Team
3 changes: 1 addition & 2 deletions app/views/layouts/application.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

- if flash[:notice]
.alert.alert-success= flash[:notice]
- else flash[:error]
- elsif flash[:error]
.alert.alert-danger= flash[:error]
%h3= flash[:notice] || flash[:error]
= yield
34 changes: 23 additions & 11 deletions app/views/questions/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
/ WHICH REPLACED THIS ^^ LINE
%p
- if @favourite
= button_to "Unfavourite", question_favourite_path(@question, @favourite), method: :delete, class: "btn btn-danger"
- else
%p= button_to "Favourite", question_favourites_path(@question), method: :post, class: "btn btn-info"

- if @question.favourited_users.present?
Favourited Users:
= @question.favourited_users.map(&:full_name).join(" , ")

%br
%hr


///Shows Categories of Question:
- if @question.categories.any?
Expand All @@ -16,17 +28,17 @@
/////New vote count system
%p

- if @vote.persisted? && @vote.is_up?
= button_to "Undo", [@question, @vote], method: :delete, class: "btn btn-primary"

- else
= form_for [@question, @vote] do |f|
= f.hidden_field :is_up, value: true
= f.submit "Vote Up", class: "btn btn-primary"
%br
= form_for [@question, @vote] do |f|
= f.hidden_field :is_up, value: false
= f.submit "Vote Down", class: "btn btn-primary"
/ - if @vote.persisted? && @vote.is_up?
/ = button_to "Undo", [@question, @vote], method: :delete, class: "btn btn-primary"
/ - else
/ = form_for [@question, @vote] do |f|
/ = f.hidden_field :is_up, value: true
/ = f.submit "Vote Up", class: "btn btn-primary"
/ %br
/ = form_for [@question, @vote] do |f|
/ = f.hidden_field :is_up, value: false
/ = f.submit "Vote Down", class: "btn btn-primary"
////////////////////Old vote count system
Expand Down
5 changes: 5 additions & 0 deletions bin/delayed_job
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false

##ADDED: Removes auto emailing when testing page locally in development
config.action_mailer.delivery_method = :letter_opener

# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log

Expand Down
8 changes: 8 additions & 0 deletions config/initializers/setup_mail.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ActionMailer::Base.smtp_settings = {
address: 'smtp.gmail.com',
port: '587',
enable_starttls_auto: true,
user_name: ENV['email_username'],
password: ENV['email_password'],
authentication: :plain
}
6 changes: 6 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@


devise_for :users

#delayed_job
match "/delayed_job" => DelayedJobWeb, :anchor => false, via: [:get, :post]


get "/jspractices" => "jspractice#index"

get "/about_us" => "home#about"
Expand All @@ -24,6 +29,7 @@
###RESOURCES BELOW DOES ALL OF THE ABOVE!!!

resources :questions do#, except: #OR# only: [:index, :new, :create]
resources :favourites, only: [:create, :destroy]
resources :votes, only: [:create, :update, :destroy]
resources :answers
#IMPORTANT: resources :answers is NESTED INSIDE resources:questions,
Expand Down
10 changes: 10 additions & 0 deletions db/migrate/20140411215552_create_favourites.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreateFavourites < ActiveRecord::Migration
def change
create_table :favourites do |t|
t.references :question, index: true
t.references :user, index: true

t.timestamps
end
end
end
22 changes: 22 additions & 0 deletions db/migrate/20140414181715_create_delayed_jobs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class CreateDelayedJobs < ActiveRecord::Migration
def self.up
create_table :delayed_jobs, :force => true do |table|
table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually.
table.text :handler, :null => false # YAML-encoded string of the object that will do work
table.text :last_error # reason for last failure (See Note below)
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
table.datetime :locked_at # Set when a client is working on this object
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
table.string :locked_by # Who is working on this object (if locked)
table.string :queue # The name of the queue this job is in
table.timestamps
end

add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
end

def self.down
drop_table :delayed_jobs
end
end
Loading

0 comments on commit bf7cfc9

Please sign in to comment.