diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..9b0b0ed
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
index 5b61ab0..2784374 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@
# Ignore bundler config.
/.bundle
+/config/initializers/app_vars.rb
+
# Ignore all logfiles and tempfiles.
/log/*
!/log/.keep
diff --git a/Gemfile b/Gemfile
index bd345bb..0efb57d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,46 +1,37 @@
source 'https://rubygems.org'
-
-
-# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.1'
-# Use postgresql as the database for Active Record
gem 'pg'
-# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
-# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
-# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'
-# See https://github.com/rails/execjs#readme for more supported runtimes
-# gem 'therubyracer', platforms: :ruby
-
-# Use jquery as the JavaScript library
gem 'jquery-rails'
-# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
-# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
-# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
-
-# Use ActiveModel has_secure_password
-# gem 'bcrypt', '~> 3.1.7'
-
+gem 'bcrypt', '~> 3.1.7'
+gem 'delayed_job_active_record'
+gem "delayed_job_web"
+gem 'bootstrap-sass'
+gem 'bootstrap-kaminari-views'
+gem 'cancancan'
+gem 'whenever', :require => false
+gem 'carrierwave'
+gem "mini_magick"
+
+
+# , :group => :development
# Use Unicorn as the app server
# gem 'unicorn'
-
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
-
group :development, :test do
- # Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
gem "hirb"
gem "awesome_print"
gem "interactive_editor"
- # Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
-
- # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
+ gem "letter_opener"
gem 'spring'
+ gem "faker"
+ gem "rails-erd"
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 50157f9..82a883e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -36,13 +36,32 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
+ addressable (2.3.8)
arel (6.0.0)
+ autoprefixer-rails (5.2.0)
+ execjs
+ json
awesome_print (1.6.1)
+ bcrypt (3.1.10)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
+ bootstrap-kaminari-views (0.0.5)
+ kaminari (>= 0.13)
+ rails (>= 3.1)
+ bootstrap-sass (3.3.4.1)
+ autoprefixer-rails (>= 5.0.0.1)
+ sass (>= 3.2.19)
builder (3.2.2)
byebug (5.0.0)
columnize (= 0.9.0)
+ cancancan (1.10.1)
+ carrierwave (0.10.0)
+ activemodel (>= 3.2.0)
+ activesupport (>= 3.2.0)
+ json (>= 1.7)
+ mime-types (>= 1.16)
+ choice (0.2.0)
+ chronic (0.10.2)
coffee-rails (4.1.0)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
@@ -52,8 +71,19 @@ GEM
coffee-script-source (1.9.1.1)
columnize (0.9.0)
debug_inspector (0.0.2)
+ delayed_job (4.0.6)
+ activesupport (>= 3.0, < 5.0)
+ delayed_job_active_record (4.0.3)
+ activerecord (>= 3.0, < 5.0)
+ delayed_job (>= 3.0, < 4.1)
+ delayed_job_web (1.2.10)
+ activerecord (> 3.0.0)
+ delayed_job (> 2.0.3)
+ sinatra (>= 1.4.4)
erubis (2.7.0)
execjs (2.5.2)
+ faker (1.4.3)
+ i18n (~> 0.5)
ffi (1.9.8)
globalid (0.3.5)
activesupport (>= 4.1.0)
@@ -69,11 +99,19 @@ GEM
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (1.8.3)
+ kaminari (0.16.3)
+ actionpack (>= 3.0.0)
+ activesupport (>= 3.0.0)
+ launchy (2.4.3)
+ addressable (~> 2.3)
+ letter_opener (1.4.1)
+ launchy (~> 2.2)
loofah (2.0.2)
nokogiri (>= 1.5.9)
mail (2.6.3)
mime-types (>= 1.16, < 3)
mime-types (2.6.1)
+ mini_magick (4.2.7)
mini_portile (0.6.2)
minitest (5.7.0)
multi_json (1.11.0)
@@ -81,6 +119,8 @@ GEM
mini_portile (~> 0.6.0)
pg (0.18.2)
rack (1.6.1)
+ rack-protection (1.5.3)
+ rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.2.1)
@@ -100,6 +140,11 @@ GEM
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
+ rails-erd (1.4.0)
+ activerecord (>= 3.2)
+ activesupport (>= 3.2)
+ choice (~> 0.2.0)
+ ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
railties (4.2.1)
@@ -109,6 +154,7 @@ GEM
thor (>= 0.18.1, < 2.0)
rake (10.4.2)
rdoc (4.2.0)
+ ruby-graphviz (1.2.2)
sass (3.4.14)
sass-rails (5.0.3)
railties (>= 4.0.0, < 5.0)
@@ -119,6 +165,10 @@ GEM
sdoc (0.4.1)
json (~> 1.7, >= 1.7.7)
rdoc (~> 4.0)
+ sinatra (1.4.6)
+ rack (~> 1.4)
+ rack-protection (~> 1.4)
+ tilt (>= 1.3, < 3)
spoon (0.0.4)
ffi
spring (1.3.6)
@@ -143,26 +193,40 @@ GEM
binding_of_caller (>= 0.7.2)
railties (>= 4.0)
sprockets-rails (>= 2.0, < 4.0)
+ whenever (0.9.4)
+ chronic (>= 0.6.3)
PLATFORMS
ruby
DEPENDENCIES
awesome_print
+ bcrypt (~> 3.1.7)
+ bootstrap-kaminari-views
+ bootstrap-sass
byebug
+ cancancan
+ carrierwave
coffee-rails (~> 4.1.0)
+ delayed_job_active_record
+ delayed_job_web
+ faker
hirb
interactive_editor
jbuilder (~> 2.0)
jquery-rails
+ letter_opener
+ mini_magick
pg
rails (= 4.2.1)
+ rails-erd
sass-rails (~> 5.0)
sdoc (~> 0.4.0)
spring
turbolinks
uglifier (>= 1.3.0)
web-console (~> 2.0)
+ whenever
BUNDLED WITH
1.10.2
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index e07c5a8..1662961 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -13,4 +13,5 @@
//= require jquery
//= require jquery_ujs
//= require turbolinks
+//= require bootstrap
//= require_tree .
diff --git a/app/assets/javascripts/comments.coffee b/app/assets/javascripts/comments.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/comments.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/javascripts/favourites.coffee b/app/assets/javascripts/favourites.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/favourites.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/javascripts/posts.coffee b/app/assets/javascripts/posts.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/posts.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/javascripts/sessions.coffee b/app/assets/javascripts/sessions.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/sessions.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/javascripts/users.coffee b/app/assets/javascripts/users.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/users.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/stylesheets/bootstrap_and_overrides.scss b/app/assets/stylesheets/bootstrap_and_overrides.scss
new file mode 100644
index 0000000..baccee2
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap_and_overrides.scss
@@ -0,0 +1,2 @@
+@import "bootstrap-sprockets";
+@import "bootstrap";
diff --git a/app/assets/stylesheets/comments.scss b/app/assets/stylesheets/comments.scss
new file mode 100644
index 0000000..3722c12
--- /dev/null
+++ b/app/assets/stylesheets/comments.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the comments controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/favourites.scss b/app/assets/stylesheets/favourites.scss
new file mode 100644
index 0000000..66cc292
--- /dev/null
+++ b/app/assets/stylesheets/favourites.scss
@@ -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/
diff --git a/app/assets/stylesheets/posts.scss b/app/assets/stylesheets/posts.scss
new file mode 100644
index 0000000..1a7e153
--- /dev/null
+++ b/app/assets/stylesheets/posts.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the posts controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss
new file mode 100644
index 0000000..7bef9cf
--- /dev/null
+++ b/app/assets/stylesheets/sessions.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the sessions controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss
new file mode 100644
index 0000000..1efc835
--- /dev/null
+++ b/app/assets/stylesheets/users.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the users controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d83690e..d8ab139 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,4 +2,21 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
+
+ def authenticate_user!
+ redirect_to new_session_path, notice: "Please sign in" unless user_signed_in?
+ end
+
+ def user_signed_in?
+ current_user.present?
+ end
+
+ helper_method :user_signed_in?
+
+ def current_user
+ @current_user ||= User.find_by_id(session[:user_id])
+ end
+
+ helper_method :current_user
+
end
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
new file mode 100644
index 0000000..9711c40
--- /dev/null
+++ b/app/controllers/comments_controller.rb
@@ -0,0 +1,58 @@
+class CommentsController < ApplicationController
+
+ before_action :authenticate_user!
+
+ def create
+ comment_params = params.require(:comment).permit(:body)
+ @post = Post.find(params[:post_id])
+ @comment = Comment.new comment_params
+ @comment.post_id = params[:post_id]
+ @comment.user = current_user
+ respond_to do |format|
+ if @comment.save
+ # PostsMailer.notify_post_owner(@comment).deliver_now
+ PostsMailer.delay.notify_post_owner(@comment)
+ format.js { render }
+ format.html { redirect_to post_path(@post) }
+ else
+ @comments = Comment.search(@post.id)
+ format.js { render :create_failure }
+ format.html { render "/posts/show" }
+ end
+ end
+ end
+
+ def edit
+ @comment = Comment.find params[:id]
+ @post = Post.find params[:post_id]
+ end
+
+ def update
+ @post = Post.find params[:post_id]
+ comment_params = params.require(:comment).permit(:body)
+ @comment = Comment.find params[:id]
+ respond_to do |format|
+ if @comment.update comment_params
+ format.js { render :update }
+ format.html {redirect_to post_path(@post)}
+ else
+ format.js { render }
+ format.html {render :edit, notice: "Failed to update."}
+ end
+ end
+ end
+
+ def destroy
+ post = Post.find params[:post_id]
+ @comment = Comment.find params[:id]
+ @comment.destroy
+ respond_to do |format|
+ format.js { render }
+ format.html {
+ flash[:notice] = "Comment successfully deleted \n\n"
+ redirect_to post
+ }
+ end
+ end
+
+end
diff --git a/app/controllers/favourites_controller.rb b/app/controllers/favourites_controller.rb
new file mode 100644
index 0000000..75964a2
--- /dev/null
+++ b/app/controllers/favourites_controller.rb
@@ -0,0 +1,28 @@
+class FavouritesController < ApplicationController
+
+
+ before_action :authenticate_user!
+
+ def create
+ post = Post.find params[:post_id]
+ favourite = post.favourites.new
+ favourite.user = current_user
+ if favourite.save
+ redirect_to post, notice: "Post favourited"
+ else
+ redirect_to post, alert: "Error!"
+ end
+ end
+
+ def destroy
+ post = Post.find params[:post_id]
+ favourite = current_user.favourites.find_by_post_id(post)
+ favourite.destroy
+ redirect_to post, notice: "Un-favourited"
+ end
+
+ def index
+ @favourites = current_user.favourites
+ end
+
+end
diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb
new file mode 100644
index 0000000..8f4f81d
--- /dev/null
+++ b/app/controllers/posts_controller.rb
@@ -0,0 +1,54 @@
+class PostsController < ApplicationController
+
+ before_action :authenticate_user!, except: [:index, :show]
+
+ def index
+ @posts = Post.all
+ end
+
+ def new
+ @post = Post.new
+ end
+
+ def create
+ post_params = params.require(:post).permit(:asset, :title, :body, {tag_ids: []})
+ @post = Post.new post_params
+ @post.user = current_user
+ if @post.save
+ redirect_to posts_path
+ else
+ flash[:alert] = "Post failed to create. Please correct errors."
+ render :new
+ end
+ end
+
+ def show
+ @post = Post.find params[:id]
+ @comment = Comment.new
+ @comments = Comment.search(@post.id)
+ @favourite = @post.favourite_for(current_user)
+ end
+
+ def destroy
+ @post = Post.find params[:id]
+ @post.destroy
+ flash[:notice] = "Successfully deleted post!"
+ redirect_to posts_path
+ end
+
+ def edit
+ @post = Post.find params[:id]
+ end
+
+ def update
+ @post = Post.find params[:id]
+ post_params = params.require(:post).permit(:asset, :title, :body, {tag_ids: []})
+ if @post.update post_params
+ flash[:notice] = "Successfully updated post!"
+ redirect_to posts_path
+ else
+ flash[:alert] = "Post failed to create."
+ render :edit
+ end
+ end
+end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
new file mode 100644
index 0000000..7976855
--- /dev/null
+++ b/app/controllers/sessions_controller.rb
@@ -0,0 +1,22 @@
+class SessionsController < ApplicationController
+
+ def new
+ end
+
+ def create
+ @user = User.find_by_email params[:email]
+ if @user && @user.authenticate(params[:password])
+ session[:user_id] = @user.id
+ redirect_to root_path, notice: "Logged in"
+ else
+ flash[:alert] = "Wrong email or password"
+ render :new
+ end
+ end
+
+ def destroy
+ session[:user_id] = nil
+ redirect_to root_path, notice: "Logged out"
+ end
+
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 0000000..e4ccd3b
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,39 @@
+class UsersController < ApplicationController
+
+ before_action :authenticate_user!, only: [:update]
+
+ def new
+ @user = User.new
+ end
+
+ def create
+ user_params = params.require(:user).permit(:first_name, :last_name, :email,
+ :password, :password_confirmation)
+ @user = User.new user_params
+ if @user.save
+ session[:user_id] = @user.id
+ redirect_to root_path, notice: "Logged In!"
+ else
+ render :new
+ end
+ end
+
+ def edit
+ @user = current_user
+ end
+
+ def update
+ user_params = params.require(:user).permit(:first_name, :last_name, :email,
+ :password, :password_confirmation)
+ @user = current_user
+ if !@user.authenticate(params[:user][:current_password])
+ flash[:alert] = "You've entered the wrong password"
+ render :edit
+ elsif @user.update(user_params)
+ redirect_to edit_users_path, notice: "Information updated"
+ else
+ render :edit
+ end
+ end
+
+end
diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb
new file mode 100644
index 0000000..0ec9ca5
--- /dev/null
+++ b/app/helpers/comments_helper.rb
@@ -0,0 +1,2 @@
+module CommentsHelper
+end
diff --git a/app/helpers/favourites_helper.rb b/app/helpers/favourites_helper.rb
new file mode 100644
index 0000000..907962e
--- /dev/null
+++ b/app/helpers/favourites_helper.rb
@@ -0,0 +1,2 @@
+module FavouritesHelper
+end
diff --git a/app/helpers/posts_helper.rb b/app/helpers/posts_helper.rb
new file mode 100644
index 0000000..a7b8cec
--- /dev/null
+++ b/app/helpers/posts_helper.rb
@@ -0,0 +1,2 @@
+module PostsHelper
+end
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
new file mode 100644
index 0000000..309f8b2
--- /dev/null
+++ b/app/helpers/sessions_helper.rb
@@ -0,0 +1,2 @@
+module SessionsHelper
+end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
new file mode 100644
index 0000000..2310a24
--- /dev/null
+++ b/app/helpers/users_helper.rb
@@ -0,0 +1,2 @@
+module UsersHelper
+end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
new file mode 100644
index 0000000..d25d889
--- /dev/null
+++ b/app/mailers/application_mailer.rb
@@ -0,0 +1,4 @@
+class ApplicationMailer < ActionMailer::Base
+ default from: "from@example.com"
+ layout 'mailer'
+end
diff --git a/app/mailers/posts_mailer.rb b/app/mailers/posts_mailer.rb
new file mode 100644
index 0000000..e58a140
--- /dev/null
+++ b/app/mailers/posts_mailer.rb
@@ -0,0 +1,15 @@
+class PostsMailer < ApplicationMailer
+
+ def notify_post_owner (comment)
+ @comment = comment
+ @user = @comment.post.user
+ mail(to: @user.email, subject: "Someone commented on your post")
+ end
+
+ def notify_post_owners_summary clustered_array
+ clustered_array.each_with_index do |cluster, i|
+ @cluster = cluster
+ mail(to: @cluster[0].post.user.email, subject: "Comments in the last 24 hours")
+ end
+ end
+end
diff --git a/app/models/category.rb b/app/models/category.rb
index 910a009..0d71b56 100644
--- a/app/models/category.rb
+++ b/app/models/category.rb
@@ -1,2 +1,7 @@
class Category < ActiveRecord::Base
+
+ has_many :posts, dependent: :nullify
+
+ validates :title, presence: true
+
end
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 45b2d38..b5a8192 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -1,2 +1,13 @@
class Comment < ActiveRecord::Base
+
+
+ validates :body, presence: true, uniqueness: { scope: :post_id }
+
+ belongs_to :post
+ belongs_to :user
+
+ def self.search id
+ Comment.where("post_id = #{id}").order("created_at desc")
+ end
+
end
diff --git a/app/models/contact.rb b/app/models/contact.rb
deleted file mode 100644
index a5ee858..0000000
--- a/app/models/contact.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-class Contact < ActiveRecord::Base
-end
diff --git a/app/models/favourite.rb b/app/models/favourite.rb
new file mode 100644
index 0000000..2ce9cc0
--- /dev/null
+++ b/app/models/favourite.rb
@@ -0,0 +1,6 @@
+class Favourite < ActiveRecord::Base
+ belongs_to :user
+ belongs_to :post
+
+ validates :user_id, uniqueness: {scope: :post_id}
+end
diff --git a/app/models/post.rb b/app/models/post.rb
new file mode 100644
index 0000000..d52ee22
--- /dev/null
+++ b/app/models/post.rb
@@ -0,0 +1,23 @@
+class Post < ActiveRecord::Base
+
+ mount_uploader :asset, AssetUploader
+
+ has_many :taggings, dependent: :destroy
+ has_many :tags, through: :taggings
+
+ has_many :favourites, dependent: :destroy
+ has_many :favouriting_users, through: :favourites, source: :user
+
+ belongs_to :user
+ belongs_to :category
+ has_many :comments, dependent: :destroy
+ validates :title, presence: true, uniqueness: true
+
+ def favourited_by?(user)
+ favourites.where(user: user).present?
+ end
+
+ def favourite_for(user)
+ favourites.find_by_user_id(user)
+ end
+end
diff --git a/app/models/post_file.rb b/app/models/post_file.rb
new file mode 100644
index 0000000..1740810
--- /dev/null
+++ b/app/models/post_file.rb
@@ -0,0 +1,3 @@
+class PostFile < ActiveRecord::Base
+ belongs_to :post
+end
diff --git a/app/models/tag.rb b/app/models/tag.rb
new file mode 100644
index 0000000..b9bd168
--- /dev/null
+++ b/app/models/tag.rb
@@ -0,0 +1,8 @@
+class Tag < ActiveRecord::Base
+
+ has_many :taggings, dependent: :destroy
+ has_many :posts, through: :taggings
+
+ validates :name, uniqueness: true
+
+end
diff --git a/app/models/tagging.rb b/app/models/tagging.rb
new file mode 100644
index 0000000..1c1cbfd
--- /dev/null
+++ b/app/models/tagging.rb
@@ -0,0 +1,6 @@
+class Tagging < ActiveRecord::Base
+ belongs_to :tag
+ belongs_to :post
+
+ validates :tag_id, uniqueness: {scope: :post_id}
+end
diff --git a/app/models/title.rb b/app/models/title.rb
deleted file mode 100644
index bee2c4c..0000000
--- a/app/models/title.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-class Title < ActiveRecord::Base
-end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 0000000..b32fcc1
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,15 @@
+class User < ActiveRecord::Base
+
+ has_many :favourites, dependent: :destroy
+ has_many :favourited_posts, through: :favourites, source: :post
+
+ has_many :posts, dependent: :destroy
+ has_many :comments, dependent: :destroy
+ has_secure_password
+ validates :email, presence: :true, uniqueness: true,
+ format: /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
+
+ def full_name
+ "#{first_name} #{last_name}".strip.squeeze(" ")
+ end
+end
diff --git a/app/uploaders/asset_uploader.rb b/app/uploaders/asset_uploader.rb
new file mode 100644
index 0000000..ec7137f
--- /dev/null
+++ b/app/uploaders/asset_uploader.rb
@@ -0,0 +1,51 @@
+# encoding: utf-8
+
+class AssetUploader < CarrierWave::Uploader::Base
+
+ # Include RMagick or MiniMagick support:
+ # include CarrierWave::RMagick
+ # include CarrierWave::MiniMagick
+
+ # Choose what kind of storage to use for this uploader:
+ storage :file
+ # storage :fog
+
+ # Override the directory where uploaded files will be stored.
+ # This is a sensible default for uploaders that are meant to be mounted:
+ def store_dir
+ "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
+ end
+
+ # Provide a default URL as a default if there hasn't been a file uploaded:
+ # def default_url
+ # # For Rails 3.1+ asset pipeline compatibility:
+ # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
+ #
+ # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
+ # end
+
+ # Process files as they are uploaded:
+ # process :scale => [200, 300]
+ #
+ # def scale(width, height)
+ # # do something
+ # end
+
+ # Create different versions of your uploaded files:
+ # version :thumb do
+ # process :resize_to_fit => [50, 50]
+ # end
+
+ #Add a white list of extensions which are allowed to be uploaded.
+ # For images you might use something like this:
+ #def extension_white_list
+ # %w(jpg jpeg gif png)
+ #end
+
+ # Override the filename of the uploaded files:
+ # Avoid using model.id or version_name here, see uploader/store.rb for details.
+ # def filename
+ # "something.jpg" if original_filename
+ # end
+
+end
diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb
new file mode 100644
index 0000000..617d81c
--- /dev/null
+++ b/app/views/comments/_comment.html.erb
@@ -0,0 +1,13 @@
+
diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb
new file mode 100644
index 0000000..d14c3af
--- /dev/null
+++ b/app/views/comments/_form.html.erb
@@ -0,0 +1,23 @@
+<%= form_for [@post, @comment], html: {class: "form-horizontal"}, remote: true do |f| %>
+
+
+ <%= f.label :body %>
+
+
+ <%= f.text_area :body, html: {class: "form-control"}, :cols => 100, :rows => 5 %>
+
+ <%= f.submit class: "btn btn-primary" %>
+
+
+
+
+ <% if @comment.errors.any? %>
+ <% @comment.errors.full_messages.each do |msg| %>
+ <%= msg %>
+ <% end %>
+ <% end %>
+
+
+
+
+<% end %>
diff --git a/app/views/comments/create.js.erb b/app/views/comments/create.js.erb
new file mode 100644
index 0000000..9b76c9d
--- /dev/null
+++ b/app/views/comments/create.js.erb
@@ -0,0 +1,4 @@
+$('#comment_box').prepend("<%= j render 'comment', comment: @comment %>")
+
+<% @comment = Comment.new %>
+$('#new_comment').replaceWith("<%= j render 'form' %>")
diff --git a/app/views/comments/create_failure.js.erb b/app/views/comments/create_failure.js.erb
new file mode 100644
index 0000000..8b5725d
--- /dev/null
+++ b/app/views/comments/create_failure.js.erb
@@ -0,0 +1 @@
+$('#new_comment').replaceWith(" <%= j render 'form' %>");
diff --git a/app/views/comments/destroy.js.erb b/app/views/comments/destroy.js.erb
new file mode 100644
index 0000000..14901e6
--- /dev/null
+++ b/app/views/comments/destroy.js.erb
@@ -0,0 +1 @@
+$("#<%= dom_id(@comment) %>").fadeOut()
diff --git a/app/views/comments/edit.html.erb b/app/views/comments/edit.html.erb
new file mode 100644
index 0000000..9479e54
--- /dev/null
+++ b/app/views/comments/edit.html.erb
@@ -0,0 +1,2 @@
+ Edit the Comment
+<%= render 'form' %>
diff --git a/app/views/comments/edit.js.erb b/app/views/comments/edit.js.erb
new file mode 100644
index 0000000..c32dbc6
--- /dev/null
+++ b/app/views/comments/edit.js.erb
@@ -0,0 +1,4 @@
+$('#<%= dom_id(@comment) %>').fadeOut()
+setTimeout(function() {
+ $("#<%= dom_id(@comment) %>").replaceWith("<%= j render 'form' %>")
+},300)
diff --git a/app/views/comments/update.js.erb b/app/views/comments/update.js.erb
new file mode 100644
index 0000000..9e41c38
--- /dev/null
+++ b/app/views/comments/update.js.erb
@@ -0,0 +1,4 @@
+$('#<%= dom_id(@comment, :edit) %>').fadeOut()
+setTimeout(function() {
+ $('#<%= dom_id(@comment, :edit) %>').replaceWith("<%= j render 'comment', comment: @comment %>")
+},300)
diff --git a/app/views/favourites/index.html.erb b/app/views/favourites/index.html.erb
new file mode 100644
index 0000000..90f7863
--- /dev/null
+++ b/app/views/favourites/index.html.erb
@@ -0,0 +1,8 @@
+Your Favourite Posts
+
+
+<% @favourites.each do |favourite| %>
+
+ <%= link_to "#{favourite.post.title}", favourite.post %>
+
+<% end %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 4191809..0a8c30d 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,16 +1,37 @@
- Quiz1
+ Murphy's Blog
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
-<%= link_to "Home", root_path %> |
-<%= link_to "All Requests", requests_path %> |
-<%= link_to "Add a Request", new_request_path %>
-<%= yield %>
+
+ <%= link_to "Home", root_path %> |
+ <%= link_to "About Me", home_about_path %> |
+ <%= link_to "All Posts", posts_path %> |
+ <%= link_to "Add a Post", new_post_path %> |
+ <% unless user_signed_in? %>
+ <%= link_to "Sign up", new_user_path %> |
+ <%= link_to "Login", new_session_path %>
+
+ <% end %>
+ <% if user_signed_in? %>
+ <%= link_to "Edit Profile", edit_users_path %> |
+ <%= link_to "Logout", sessions_path, method: :delete %> |
+ Hi there <%= current_user.full_name %>, here are your <%= current_user.favourites.length %>
+ <%= link_to 'Favourite Posts', user_favourites_path(current_user) %>
+
+ <% end %>
+ <% if flash[:alert] %>
+
<%= flash[:alert] %>
+ <% end %>
+ <% if flash[:notice] %>
+
<%= flash[:notice] %>
+ <% end %>
+ <%= yield %>
+
diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb
new file mode 100644
index 0000000..991cf0f
--- /dev/null
+++ b/app/views/layouts/mailer.html.erb
@@ -0,0 +1,5 @@
+
+
+ <%= yield %>
+
+
diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb
new file mode 100644
index 0000000..37f0bdd
--- /dev/null
+++ b/app/views/layouts/mailer.text.erb
@@ -0,0 +1 @@
+<%= yield %>
diff --git a/app/views/posts/_form.html.erb b/app/views/posts/_form.html.erb
new file mode 100644
index 0000000..dc824b1
--- /dev/null
+++ b/app/views/posts/_form.html.erb
@@ -0,0 +1,27 @@
+<% if @post.errors.any? %>
+
+ <% @post.errors.full_messages.each do |msg| %>
+ - <%= msg %>. Please correct this.
+ <% end %>
+
+<% end %>
+
+<%= form_for @post do |f| %>
+
+ <%= f.label :title %>
+ <%= f.text_field :title %>
+
+
+ <%= f.label :asset %>
+ <%= f.file_field :asset %>
+
+
+ <%= f.label :body %>
+ <%= f.text_area :body %>
+
+
+
+ <%= f.collection_check_boxes :tag_ids, Tag.all, :id, :name %>
+
+ <%= f.submit "Submit" %>
+<% end %>
diff --git a/app/views/posts/edit.html.erb b/app/views/posts/edit.html.erb
new file mode 100644
index 0000000..fdadb73
--- /dev/null
+++ b/app/views/posts/edit.html.erb
@@ -0,0 +1,5 @@
+
Edit this post to suit your needs!
+
+<%= flash.alert %>
+
+<%= render "form" %>
diff --git a/app/views/posts/index.html.erb b/app/views/posts/index.html.erb
new file mode 100644
index 0000000..0ffd541
--- /dev/null
+++ b/app/views/posts/index.html.erb
@@ -0,0 +1,11 @@
+
All Posts
+
+<%= flash.notice %>
+
+<% @posts.each do |post| %>
+
+
<%= link_to post.title, post_path(post) %>
+
+
+
+<% end %>
diff --git a/app/views/posts/new.html.erb b/app/views/posts/new.html.erb
new file mode 100644
index 0000000..2700c33
--- /dev/null
+++ b/app/views/posts/new.html.erb
@@ -0,0 +1,3 @@
+
Create a New Post!
+
+<%= render "form" %>
diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb
new file mode 100644
index 0000000..aecd5cc
--- /dev/null
+++ b/app/views/posts/show.html.erb
@@ -0,0 +1,32 @@
+
+
+
<%= @post.title %>
+
+
<%= @post.body %>
+<% if current_user.present? %>
+ <% if @post.favourited_by?(current_user) %>
+ <%= link_to "Un-Favourite", post_favourite_path(@post, @favourite),
+ method: :delete %>
+ <% else %>
+ <%= link_to "Favourite", post_favourites_path(@post), method: :post %>
+ <% end %>
+ <%= link_to "Edit", edit_post_path(@post) %>
+ <%= link_to "Delete", post_path(@post), method: :delete, remote: true,
+ data: { confirm: "Are you sure you want to delete this?" } %>
+<% end %>
+
+
+<%= render "/comments/form" %>
+
+
diff --git a/app/views/posts_mailer/notify_post_owner.html.erb b/app/views/posts_mailer/notify_post_owner.html.erb
new file mode 100644
index 0000000..f96f146
--- /dev/null
+++ b/app/views/posts_mailer/notify_post_owner.html.erb
@@ -0,0 +1,2 @@
+Hey <%= @user.full_name %>! Someone commented, "<%= @comment.body %>" on your
+post titled <%= @comment.post.title %>.
diff --git a/app/views/posts_mailer/notify_post_owners_summary.html.erb b/app/views/posts_mailer/notify_post_owners_summary.html.erb
new file mode 100644
index 0000000..8c38993
--- /dev/null
+++ b/app/views/posts_mailer/notify_post_owners_summary.html.erb
@@ -0,0 +1,7 @@
+Here are the comments made in the last 24 hours, <%= @cluster[0].post.user.full_name %>
+
+<% @cluster.each do |comment| %>
+
+ <%= comment.user.full_name %> said: <%= comment.body %>
+
+<% end %>
diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb
new file mode 100644
index 0000000..bd48717
--- /dev/null
+++ b/app/views/sessions/new.html.erb
@@ -0,0 +1,15 @@
+
Sign in!
+
+<%= form_tag sessions_path do %>
+
+
+ <%= label_tag :email %>
+ <%= text_field_tag :email %>
+
+
+ <%= label_tag :password %>
+ <%= password_field_tag :password %>
+
+ <%= submit_tag %>
+
+<% end %>
diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb
new file mode 100644
index 0000000..457fca2
--- /dev/null
+++ b/app/views/users/_form.html.erb
@@ -0,0 +1,43 @@
+<% if @user.errors.any? %>
+
+ <% @user.errors.full_messages.each do |msg| %>
+ -
+
<%= msg %>
+
+ <% end %>
+
+<% end %>
+
+
+<%= form_for @user, url: users_path do |f| %>
+
+
+ <%= f.label :first_name %>
+ <%= f.text_field :first_name %>
+
+
+ <%= f.label :last_name %>
+ <%= f.text_field :last_name %>
+
+
+ <%= f.label :email %>
+ <%= f.email_field :email %>
+
+ <% if @user.persisted? %>
+
+
Please enter your current password to implement changes
+ <%= f.label :current_password %>
+ <%= f.password_field :current_password %>
+
+ <% end %>
+
+ <%= f.label :password %>
+ <%= f.password_field :password %>
+
+
+ <%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation %>
+
+
+ <%= f.submit %>
+<% end %>
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb
new file mode 100644
index 0000000..e7cae8c
--- /dev/null
+++ b/app/views/users/edit.html.erb
@@ -0,0 +1,3 @@
+
Change your profile
+
+<%= render "form" %>
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
new file mode 100644
index 0000000..f07da2d
--- /dev/null
+++ b/app/views/users/new.html.erb
@@ -0,0 +1,3 @@
+
Create a new User
+
+<%= render "form" %>
diff --git a/bin/delayed_job b/bin/delayed_job
new file mode 100755
index 0000000..edf1959
--- /dev/null
+++ b/bin/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/config/application.rb b/config/application.rb
index ecd54d7..de85bd8 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -20,6 +20,8 @@ class Application < Rails::Application
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
+ config.active_job.queue_adapter = :delayed_job
+
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
end
diff --git a/config/environments/development.rb b/config/environments/development.rb
index b55e214..50162d1 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -36,6 +36,7 @@
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
+ config.action_mailer.delivery_method = :letter_opener
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end
diff --git a/config/initializers/core_extensions.rb b/config/initializers/core_extensions.rb
new file mode 100644
index 0000000..557eef0
--- /dev/null
+++ b/config/initializers/core_extensions.rb
@@ -0,0 +1,16 @@
+module Enumerable
+ # clumps adjacent elements together
+ # >> [2,2,2,3,3,4,2,2,1].cluster{|x| x}
+ # => [[2, 2, 2], [3, 3], [4], [2, 2], [1]]
+ def cluster
+ cluster = []
+ each do |element|
+ if cluster.last && yield(cluster.last.last) == yield(element)
+ cluster.last << element
+ else
+ cluster << [element]
+ end
+ end
+ cluster
+ end
+end
diff --git a/config/initializers/setup_mail.rb b/config/initializers/setup_mail.rb
new file mode 100644
index 0000000..6c18985
--- /dev/null
+++ b/config/initializers/setup_mail.rb
@@ -0,0 +1,8 @@
+ActionMailer::Base.smtp_settings = {
+ address: "smtp.gmail.com",
+ port: "587",
+ enable_starttls_auto: true,
+ authentication: :plain,
+ user_name: ENV["email_user_name"],
+ password: ENV["email_password"]
+}
diff --git a/config/routes.rb b/config/routes.rb
index 3f66539..d25bff5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,56 +1,23 @@
Rails.application.routes.draw do
- # The priority is based upon order of creation: first created -> highest priority.
- # See how all your routes lay out with "rake routes".
- # You can have the root of your site routed with "root"
- # root 'welcome#index'
+ root "home#index"
+ get "/home/about" => "home#about"
- # Example of regular route:
- # get 'products/:id' => 'catalog#view'
+ match "/delayed_job" => DelayedJobWeb, :anchor => false, via: [:get, :post]
- # Example of named route that can be invoked with purchase_url(id: product.id)
- # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
+ resources :users, only: [:new, :create] do
+ resources :favourites, only: [:index]
+ get :edit, on: :collection
+ patch :update, on: :collection
+ end
- # Example resource route (maps HTTP verbs to controller actions automatically):
- # resources :products
+ resources :sessions, only: [:new, :create] do
+ delete :destroy, on: :collection
+ end
- # Example resource route with options:
- # resources :products do
- # member do
- # get 'short'
- # post 'toggle'
- # end
- #
- # collection do
- # get 'sold'
- # end
- # end
+ resources :posts do
+ resources :favourites, only: [:destroy, :create]
+ resources :comments
+ end
- # Example resource route with sub-resources:
- # resources :products do
- # resources :comments, :sales
- # resource :seller
- # end
-
- # Example resource route with more complex sub-resources:
- # resources :products do
- # resources :comments
- # resources :sales do
- # get 'recent', on: :collection
- # end
- # end
-
- # Example resource route with concerns:
- # concern :toggleable do
- # post 'toggle'
- # end
- # resources :posts, concerns: :toggleable
- # resources :photos, concerns: :toggleable
-
- # Example resource route within a namespace:
- # namespace :admin do
- # # Directs /admin/products/* to Admin::ProductsController
- # # (app/controllers/admin/products_controller.rb)
- # resources :products
- # end
end
diff --git a/config/schedule.rb b/config/schedule.rb
new file mode 100644
index 0000000..c1df104
--- /dev/null
+++ b/config/schedule.rb
@@ -0,0 +1,26 @@
+# Use this file to easily define all of your cron jobs.
+#
+# It's helpful, but not entirely necessary to understand cron before proceeding.
+# http://en.wikipedia.org/wiki/Cron
+
+# Example:
+#
+# set :output, "/path/to/my/cron_log.log"
+#
+# every 2.hours do
+# command "/usr/bin/some_great_command"
+# runner "MyModel.some_method"
+# rake "some:great:rake:task"
+# end
+#
+# every 4.days do
+# runner "AnotherModel.prune_old_records"
+# end
+
+# Learn more: http://github.com/javan/whenever
+set :environment, "development"
+set :output, {:error => "log/cron_error_log.log", :standard => "log/cron_log.log"}
+
+every :day, :at => '6:28pm' do
+ rake "post:comments"
+end
diff --git a/db/.DS_Store b/db/.DS_Store
new file mode 100644
index 0000000..fce5605
Binary files /dev/null and b/db/.DS_Store differ
diff --git a/db/migrate/20150609015548_create_titles.rb b/db/migrate/20150609015548_create_titles.rb
deleted file mode 100644
index 099aa1b..0000000
--- a/db/migrate/20150609015548_create_titles.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class CreateTitles < ActiveRecord::Migration
- def change
- create_table :titles do |t|
- t.text :body
-
- t.timestamps null: false
- end
- end
-end
diff --git a/db/migrate/20150609015835_create_contacts.rb b/db/migrate/20150609015835_create_contacts.rb
deleted file mode 100644
index 5298b22..0000000
--- a/db/migrate/20150609015835_create_contacts.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class CreateContacts < ActiveRecord::Migration
- def change
- create_table :contacts do |t|
- t.string :email
- t.string :name
- t.string :subject
- t.text :message
-
- t.timestamps null: false
- end
- end
-end
diff --git a/db/migrate/20150609024027_create_posts.rb b/db/migrate/20150609024027_create_posts.rb
new file mode 100644
index 0000000..691c505
--- /dev/null
+++ b/db/migrate/20150609024027_create_posts.rb
@@ -0,0 +1,10 @@
+class CreatePosts < ActiveRecord::Migration
+ def change
+ create_table :posts do |t|
+ t.string :title
+ t.text :body
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20150614212959_create_users.rb b/db/migrate/20150614212959_create_users.rb
new file mode 100644
index 0000000..e22193e
--- /dev/null
+++ b/db/migrate/20150614212959_create_users.rb
@@ -0,0 +1,12 @@
+class CreateUsers < ActiveRecord::Migration
+ def change
+ create_table :users do |t|
+ t.string :first_name
+ t.string :last_name
+ t.string :email
+ t.string :password_digest
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20150614213024_add_user_reference_to_posts.rb b/db/migrate/20150614213024_add_user_reference_to_posts.rb
new file mode 100644
index 0000000..07fdc05
--- /dev/null
+++ b/db/migrate/20150614213024_add_user_reference_to_posts.rb
@@ -0,0 +1,5 @@
+class AddUserReferenceToPosts < ActiveRecord::Migration
+ def change
+ add_reference :posts, :user, index: true, foreign_key: true
+ end
+end
diff --git a/db/migrate/20150614213039_add_user_reference_to_comments.rb b/db/migrate/20150614213039_add_user_reference_to_comments.rb
new file mode 100644
index 0000000..51fc510
--- /dev/null
+++ b/db/migrate/20150614213039_add_user_reference_to_comments.rb
@@ -0,0 +1,5 @@
+class AddUserReferenceToComments < ActiveRecord::Migration
+ def change
+ add_reference :comments, :user, index: true, foreign_key: true
+ end
+end
diff --git a/db/migrate/20150614214423_create_post_files.rb b/db/migrate/20150614214423_create_post_files.rb
new file mode 100644
index 0000000..ec4cb97
--- /dev/null
+++ b/db/migrate/20150614214423_create_post_files.rb
@@ -0,0 +1,11 @@
+class CreatePostFiles < ActiveRecord::Migration
+ def change
+ create_table :post_files do |t|
+ t.string :name
+ t.text :description
+ t.references :post, index: true, foreign_key: true
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20150619002353_create_favourites.rb b/db/migrate/20150619002353_create_favourites.rb
new file mode 100644
index 0000000..bf98360
--- /dev/null
+++ b/db/migrate/20150619002353_create_favourites.rb
@@ -0,0 +1,10 @@
+class CreateFavourites < ActiveRecord::Migration
+ def change
+ create_table :favourites do |t|
+ t.references :user, index: true, foreign_key: true
+ t.references :post, index: true, foreign_key: true
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20150619014257_create_tags.rb b/db/migrate/20150619014257_create_tags.rb
new file mode 100644
index 0000000..965cd7a
--- /dev/null
+++ b/db/migrate/20150619014257_create_tags.rb
@@ -0,0 +1,9 @@
+class CreateTags < ActiveRecord::Migration
+ def change
+ create_table :tags do |t|
+ t.string :name
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20150619014310_create_taggings.rb b/db/migrate/20150619014310_create_taggings.rb
new file mode 100644
index 0000000..0dd5c85
--- /dev/null
+++ b/db/migrate/20150619014310_create_taggings.rb
@@ -0,0 +1,10 @@
+class CreateTaggings < ActiveRecord::Migration
+ def change
+ create_table :taggings do |t|
+ t.references :tag, index: true, foreign_key: true
+ t.references :post, index: true, foreign_key: true
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20150620220111_create_delayed_jobs.rb b/db/migrate/20150620220111_create_delayed_jobs.rb
new file mode 100644
index 0000000..27fdcf6
--- /dev/null
+++ b/db/migrate/20150620220111_create_delayed_jobs.rb
@@ -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 null: true
+ end
+
+ add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
+ end
+
+ def self.down
+ drop_table :delayed_jobs
+ end
+end
diff --git a/db/migrate/20150703013105_add_asset_to_posts.rb b/db/migrate/20150703013105_add_asset_to_posts.rb
new file mode 100644
index 0000000..bb29633
--- /dev/null
+++ b/db/migrate/20150703013105_add_asset_to_posts.rb
@@ -0,0 +1,5 @@
+class AddAssetToPosts < ActiveRecord::Migration
+ def change
+ add_column :posts, :asset, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a5043cb..7812a93 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20150609015835) do
+ActiveRecord::Schema.define(version: 20150703013105) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -26,8 +26,13 @@
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "post_id"
+ t.integer "user_id"
end
+ add_index "comments", ["post_id"], name: "index_comments_on_post_id", using: :btree
+ add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree
+
create_table "contacts", force: :cascade do |t|
t.string "email"
t.string "name"
@@ -37,10 +42,90 @@
t.datetime "updated_at", null: false
end
+ create_table "delayed_jobs", force: :cascade do |t|
+ t.integer "priority", default: 0, null: false
+ t.integer "attempts", default: 0, null: false
+ t.text "handler", null: false
+ t.text "last_error"
+ t.datetime "run_at"
+ t.datetime "locked_at"
+ t.datetime "failed_at"
+ t.string "locked_by"
+ t.string "queue"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree
+
+ create_table "favourites", force: :cascade do |t|
+ t.integer "user_id"
+ t.integer "post_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "favourites", ["post_id"], name: "index_favourites_on_post_id", using: :btree
+ add_index "favourites", ["user_id"], name: "index_favourites_on_user_id", using: :btree
+
+ create_table "post_files", force: :cascade do |t|
+ t.string "name"
+ t.text "description"
+ t.integer "post_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "post_files", ["post_id"], name: "index_post_files_on_post_id", using: :btree
+
+ create_table "posts", force: :cascade do |t|
+ t.string "title"
+ t.text "body"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.integer "user_id"
+ t.string "asset"
+ end
+
+ add_index "posts", ["user_id"], name: "index_posts_on_user_id", using: :btree
+
+ create_table "taggings", force: :cascade do |t|
+ t.integer "tag_id"
+ t.integer "post_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "taggings", ["post_id"], name: "index_taggings_on_post_id", using: :btree
+ add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree
+
+ create_table "tags", force: :cascade do |t|
+ t.string "name"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "titles", force: :cascade do |t|
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
+ create_table "users", force: :cascade do |t|
+ t.string "first_name"
+ t.string "last_name"
+ t.string "email"
+ t.string "password_digest"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_foreign_key "comments", "posts"
+ add_foreign_key "comments", "users"
+ add_foreign_key "favourites", "posts"
+ add_foreign_key "favourites", "users"
+ add_foreign_key "post_files", "posts"
+ add_foreign_key "posts", "users"
+ add_foreign_key "taggings", "posts"
+ add_foreign_key "taggings", "tags"
end
diff --git a/db/seeds.rb b/db/seeds.rb
index 4edb1e8..a6f8dda 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -5,3 +5,7 @@
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)
+
+['1','2','3','4','5','6','7'].each do |num|
+ Tag.create name: num
+end
diff --git a/erd.pdf b/erd.pdf
new file mode 100644
index 0000000..12bd30f
Binary files /dev/null and b/erd.pdf differ
diff --git a/lib/tasks/post.rake b/lib/tasks/post.rake
new file mode 100644
index 0000000..a9efbe7
--- /dev/null
+++ b/lib/tasks/post.rake
@@ -0,0 +1,32 @@
+namespace :post do
+ desc "Tasks associated with posts"
+ task comments: :environment do
+ new_comments = []
+ comments = Comment.includes(post: :user).where('created_at > ?', 1.day.ago)
+ comments.each {|comment| new_comments << comment}
+ #Comment.where("created_at > ?", 1.day.ago).each {|comment| new_comments << comment}
+ sorted_new_comments = new_comments.sort_by { |comment| comment.post.user }
+ #new_comments.each { |comment| p comment.post.user }
+ #p sorted_new_comments == new_comments
+ #sorted_new_comments.each { |comment| p comment.post.user }
+ @clustered_comments = sorted_new_comments.cluster { |comment| comment.post.user }
+ @clustered_comments.each {|c| p c[0].post.user.email}
+ PostsMailer.notify_post_owners_summary(@clustered_comments).deliver_now
+ end
+end
+
+
+# Stretch: Setup a rake task that does the following:
+# Make a summary (list) of all newly created comments that that day for posts
+# Send an email with the summary to posts owners
+
+#find all comments less than a day old
+#
+#group them somehow
+#
+#User.all.each
+#Post.all.each do |post|
+# post.comments.where("created_at < ?", 1.day.ago).each do |comment|
+# p comment.body
+# end
+#end
diff --git a/public/uploads/post/asset/15/Photo_on_2015-06-20_at_7.49_AM.jpg b/public/uploads/post/asset/15/Photo_on_2015-06-20_at_7.49_AM.jpg
new file mode 100644
index 0000000..4209dee
Binary files /dev/null and b/public/uploads/post/asset/15/Photo_on_2015-06-20_at_7.49_AM.jpg differ
diff --git a/public/uploads/post/asset/16/config.ru b/public/uploads/post/asset/16/config.ru
new file mode 100644
index 0000000..bd83b25
--- /dev/null
+++ b/public/uploads/post/asset/16/config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run Rails.application
diff --git a/test/controllers/comments_controller_test.rb b/test/controllers/comments_controller_test.rb
new file mode 100644
index 0000000..2ec71b4
--- /dev/null
+++ b/test/controllers/comments_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class CommentsControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/controllers/favourites_controller_test.rb b/test/controllers/favourites_controller_test.rb
new file mode 100644
index 0000000..31785f5
--- /dev/null
+++ b/test/controllers/favourites_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class FavouritesControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/controllers/posts_controller_test.rb b/test/controllers/posts_controller_test.rb
new file mode 100644
index 0000000..7a6ee4f
--- /dev/null
+++ b/test/controllers/posts_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class PostsControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb
new file mode 100644
index 0000000..d30ebc3
--- /dev/null
+++ b/test/controllers/sessions_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class SessionsControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
new file mode 100644
index 0000000..d23f182
--- /dev/null
+++ b/test/controllers/users_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class UsersControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/fixtures/favourites.yml b/test/fixtures/favourites.yml
new file mode 100644
index 0000000..a5aae8c
--- /dev/null
+++ b/test/fixtures/favourites.yml
@@ -0,0 +1,9 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ user_id:
+ post_id:
+
+two:
+ user_id:
+ post_id:
diff --git a/test/fixtures/contacts.yml b/test/fixtures/post_files.yml
similarity index 54%
rename from test/fixtures/contacts.yml
rename to test/fixtures/post_files.yml
index db36c32..20f209c 100644
--- a/test/fixtures/contacts.yml
+++ b/test/fixtures/post_files.yml
@@ -1,13 +1,11 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
- email: MyString
name: MyString
- subject: MyString
- message: MyText
+ description: MyText
+ post_id:
two:
- email: MyString
name: MyString
- subject: MyString
- message: MyText
+ description: MyText
+ post_id:
diff --git a/test/fixtures/titles.yml b/test/fixtures/posts.yml
similarity index 78%
rename from test/fixtures/titles.yml
rename to test/fixtures/posts.yml
index e46420e..e192dee 100644
--- a/test/fixtures/titles.yml
+++ b/test/fixtures/posts.yml
@@ -1,7 +1,9 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
+ title: MyString
body: MyText
two:
+ title: MyString
body: MyText
diff --git a/test/fixtures/taggings.yml b/test/fixtures/taggings.yml
new file mode 100644
index 0000000..cf134d9
--- /dev/null
+++ b/test/fixtures/taggings.yml
@@ -0,0 +1,9 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ tag_id:
+ post_id:
+
+two:
+ tag_id:
+ post_id:
diff --git a/test/fixtures/tags.yml b/test/fixtures/tags.yml
new file mode 100644
index 0000000..56066c6
--- /dev/null
+++ b/test/fixtures/tags.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+
+two:
+ name: MyString
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
new file mode 100644
index 0000000..dacc14f
--- /dev/null
+++ b/test/fixtures/users.yml
@@ -0,0 +1,13 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ first_name: MyString
+ last_name: MyString
+ email: MyString
+ password_digest: MyString
+
+two:
+ first_name: MyString
+ last_name: MyString
+ email: MyString
+ password_digest: MyString
diff --git a/test/mailers/posts_mailer_test.rb b/test/mailers/posts_mailer_test.rb
new file mode 100644
index 0000000..b5a885f
--- /dev/null
+++ b/test/mailers/posts_mailer_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class PostsMailerTest < ActionMailer::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/mailers/previews/posts_mailer_preview.rb b/test/mailers/previews/posts_mailer_preview.rb
new file mode 100644
index 0000000..ef4ebb9
--- /dev/null
+++ b/test/mailers/previews/posts_mailer_preview.rb
@@ -0,0 +1,4 @@
+# Preview all emails at http://localhost:3000/rails/mailers/posts_mailer
+class PostsMailerPreview < ActionMailer::Preview
+
+end
diff --git a/test/models/favourite_test.rb b/test/models/favourite_test.rb
new file mode 100644
index 0000000..8bbf41d
--- /dev/null
+++ b/test/models/favourite_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class FavouriteTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/post_file_test.rb b/test/models/post_file_test.rb
new file mode 100644
index 0000000..73e8e0d
--- /dev/null
+++ b/test/models/post_file_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class PostFileTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/title_test.rb b/test/models/post_test.rb
similarity index 64%
rename from test/models/title_test.rb
rename to test/models/post_test.rb
index 954b9e3..6d9d463 100644
--- a/test/models/title_test.rb
+++ b/test/models/post_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class TitleTest < ActiveSupport::TestCase
+class PostTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
diff --git a/test/models/contact_test.rb b/test/models/tag_test.rb
similarity index 63%
rename from test/models/contact_test.rb
rename to test/models/tag_test.rb
index ccef1f9..b8498a1 100644
--- a/test/models/contact_test.rb
+++ b/test/models/tag_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class ContactTest < ActiveSupport::TestCase
+class TagTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
diff --git a/test/models/tagging_test.rb b/test/models/tagging_test.rb
new file mode 100644
index 0000000..77dbeac
--- /dev/null
+++ b/test/models/tagging_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class TaggingTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
new file mode 100644
index 0000000..82f61e0
--- /dev/null
+++ b/test/models/user_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end