diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..b0aeedb
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8672e44
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+# See https://help.github.com/articles/ignoring-files for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile '~/.gitignore_global'
+
+# Ignore bundler config.
+/.bundle
+
+# Ignore the default SQLite database.
+/db/*.sqlite3
+/db/*.sqlite3-journal
+
+# Ignore all logfiles and tempfiles.
+/log/*
+!/log/.keep
+/tmp
+
+# Ignore Spring files.
+/spring/*.pid
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..399da94
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,36 @@
+source 'https://rubygems.org'
+
+ gem 'rails', '4.2.4'
+ gem 'bootstrap-sass', '3.3.0'
+ gem 'faker', '1.4.2'
+ gem 'bcrypt', '3.1.7'
+ gem 'sass-rails', '5.0.2'
+ gem 'uglifier', '2.5.3'
+ gem 'coffee-rails', '4.1.0'
+ gem 'jquery-rails', '4.0.3'
+ gem 'turbolinks', '2.3.0'
+ gem 'jbuilder', '2.2.3'
+ gem 'will_paginate', '3.0.7'
+ gem 'bootstrap-will_paginate', '0.0.10'
+ gem 'sdoc', '0.4.0', group: :doc
+
+
+group :development, :test do
+ gem 'sqlite3', '1.3.9'
+ gem 'byebug', '3.4.0'
+ gem 'web-console', '2.0.0.beta3'
+ gem 'spring', '1.1.3'
+end
+
+group :test do
+ gem 'minitest-reporters', '1.0.5'
+ gem 'mini_backtrace', '0.1.3'
+ gem 'guard-minitest', '2.3.1'
+end
+
+group :production do
+ gem 'pg', '0.17.1'
+ gem 'rails_12factor', '0.0.2'
+ gem 'puma', '2.11.1'
+end
+
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..4449376
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,231 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (4.2.4)
+ actionpack (= 4.2.4)
+ actionview (= 4.2.4)
+ activejob (= 4.2.4)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ actionpack (4.2.4)
+ actionview (= 4.2.4)
+ activesupport (= 4.2.4)
+ rack (~> 1.6)
+ rack-test (~> 0.6.2)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (4.2.4)
+ activesupport (= 4.2.4)
+ builder (~> 3.1)
+ erubis (~> 2.7.0)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ activejob (4.2.4)
+ activesupport (= 4.2.4)
+ globalid (>= 0.3.0)
+ activemodel (4.2.4)
+ activesupport (= 4.2.4)
+ builder (~> 3.1)
+ activerecord (4.2.4)
+ activemodel (= 4.2.4)
+ activesupport (= 4.2.4)
+ arel (~> 6.0)
+ activesupport (4.2.4)
+ i18n (~> 0.7)
+ json (~> 1.7, >= 1.7.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ ansi (1.5.0)
+ arel (6.0.3)
+ bcrypt (3.1.7)
+ binding_of_caller (0.7.3.pre1)
+ debug_inspector (>= 0.0.1)
+ bootstrap-sass (3.3.0.0)
+ sass (~> 3.2)
+ bootstrap-will_paginate (0.0.10)
+ will_paginate
+ builder (3.2.2)
+ byebug (3.4.0)
+ columnize (~> 0.8)
+ debugger-linecache (~> 1.2)
+ slop (~> 3.6)
+ coderay (1.1.0)
+ coffee-rails (4.1.0)
+ coffee-script (>= 2.2.0)
+ railties (>= 4.0.0, < 5.0)
+ coffee-script (2.4.1)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.9.1.1)
+ columnize (0.9.0)
+ debug_inspector (0.0.2)
+ debugger-linecache (1.2.0)
+ erubis (2.7.0)
+ execjs (2.6.0)
+ faker (1.4.2)
+ i18n (~> 0.5)
+ ffi (1.9.10)
+ formatador (0.2.5)
+ globalid (0.3.6)
+ activesupport (>= 4.1.0)
+ guard (2.13.0)
+ formatador (>= 0.2.4)
+ listen (>= 2.7, <= 4.0)
+ lumberjack (~> 1.0)
+ nenv (~> 0.1)
+ notiffany (~> 0.0)
+ pry (>= 0.9.12)
+ shellany (~> 0.0)
+ thor (>= 0.18.1)
+ guard-minitest (2.3.1)
+ guard (~> 2.0)
+ minitest (>= 3.0)
+ i18n (0.7.0)
+ jbuilder (2.2.3)
+ activesupport (>= 3.0.0, < 5)
+ multi_json (~> 1.2)
+ jquery-rails (4.0.3)
+ rails-dom-testing (~> 1.0)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
+ json (1.8.3)
+ listen (3.0.3)
+ rb-fsevent (>= 0.9.3)
+ rb-inotify (>= 0.9)
+ loofah (2.0.3)
+ nokogiri (>= 1.5.9)
+ lumberjack (1.0.9)
+ mail (2.6.3)
+ mime-types (>= 1.16, < 3)
+ method_source (0.8.2)
+ mime-types (2.6.2)
+ mini_backtrace (0.1.3)
+ minitest (> 1.2.0)
+ rails (>= 2.3.3)
+ mini_portile (0.6.2)
+ minitest (5.8.1)
+ minitest-reporters (1.0.5)
+ ansi
+ builder
+ minitest (>= 5.0)
+ ruby-progressbar
+ multi_json (1.11.2)
+ nenv (0.2.0)
+ nokogiri (1.6.6.2)
+ mini_portile (~> 0.6.0)
+ notiffany (0.0.8)
+ nenv (~> 0.1)
+ shellany (~> 0.0)
+ pg (0.17.1)
+ pry (0.10.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.8.1)
+ slop (~> 3.4)
+ puma (2.11.1)
+ rack (>= 1.1, < 2.0)
+ rack (1.6.4)
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (4.2.4)
+ actionmailer (= 4.2.4)
+ actionpack (= 4.2.4)
+ actionview (= 4.2.4)
+ activejob (= 4.2.4)
+ activemodel (= 4.2.4)
+ activerecord (= 4.2.4)
+ activesupport (= 4.2.4)
+ bundler (>= 1.3.0, < 2.0)
+ railties (= 4.2.4)
+ sprockets-rails
+ rails-deprecated_sanitizer (1.0.3)
+ activesupport (>= 4.2.0.alpha)
+ rails-dom-testing (1.0.7)
+ activesupport (>= 4.2.0.beta, < 5.0)
+ nokogiri (~> 1.6.0)
+ rails-deprecated_sanitizer (>= 1.0.1)
+ rails-html-sanitizer (1.0.2)
+ loofah (~> 2.0)
+ rails_12factor (0.0.2)
+ rails_serve_static_assets
+ rails_stdout_logging
+ rails_serve_static_assets (0.0.4)
+ rails_stdout_logging (0.0.4)
+ railties (4.2.4)
+ actionpack (= 4.2.4)
+ activesupport (= 4.2.4)
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rake (10.4.2)
+ rb-fsevent (0.9.6)
+ rb-inotify (0.9.5)
+ ffi (>= 0.5.0)
+ rdoc (4.2.0)
+ ruby-progressbar (1.7.5)
+ sass (3.4.19)
+ sass-rails (5.0.2)
+ railties (>= 4.0.0, < 5.0)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (~> 1.1)
+ sdoc (0.4.0)
+ json (~> 1.8)
+ rdoc (~> 4.0, < 5.0)
+ shellany (0.0.1)
+ slop (3.6.0)
+ spring (1.1.3)
+ sprockets (3.4.0)
+ rack (> 1, < 3)
+ sprockets-rails (2.3.3)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ sprockets (>= 2.8, < 4.0)
+ sqlite3 (1.3.9)
+ thor (0.19.1)
+ thread_safe (0.3.5)
+ tilt (1.4.1)
+ turbolinks (2.3.0)
+ coffee-rails
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+ uglifier (2.5.3)
+ execjs (>= 0.3.0)
+ json (>= 1.8.0)
+ web-console (2.0.0.beta3)
+ activemodel (~> 4.0)
+ binding_of_caller (= 0.7.3.pre1)
+ railties (~> 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ will_paginate (3.0.7)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bcrypt (= 3.1.7)
+ bootstrap-sass (= 3.3.0)
+ bootstrap-will_paginate (= 0.0.10)
+ byebug (= 3.4.0)
+ coffee-rails (= 4.1.0)
+ faker (= 1.4.2)
+ guard-minitest (= 2.3.1)
+ jbuilder (= 2.2.3)
+ jquery-rails (= 4.0.3)
+ mini_backtrace (= 0.1.3)
+ minitest-reporters (= 1.0.5)
+ pg (= 0.17.1)
+ puma (= 2.11.1)
+ rails (= 4.2.4)
+ rails_12factor (= 0.0.2)
+ sass-rails (= 5.0.2)
+ sdoc (= 0.4.0)
+ spring (= 1.1.3)
+ sqlite3 (= 1.3.9)
+ turbolinks (= 2.3.0)
+ uglifier (= 2.5.3)
+ web-console (= 2.0.0.beta3)
+ will_paginate (= 3.0.7)
+
+BUNDLED WITH
+ 1.10.6
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..528ca4b
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: bundle exec puma -C config/puma.rb
\ No newline at end of file
diff --git a/README.rdoc b/README.rdoc
new file mode 100644
index 0000000..dd4e97e
--- /dev/null
+++ b/README.rdoc
@@ -0,0 +1,28 @@
+== README
+
+This README would normally document whatever steps are necessary to get the
+application up and running.
+
+Things you may want to cover:
+
+* Ruby version
+
+* System dependencies
+
+* Configuration
+
+* Database creation
+
+* Database initialization
+
+* How to run the test suite
+
+* Services (job queues, cache servers, search engines, etc.)
+
+* Deployment instructions
+
+* ...
+
+
+Please feel free to use a different markup language if you do not plan to run
+rake doc:app.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..ba6b733
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,6 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Rails.application.load_tasks
diff --git a/app/.DS_Store b/app/.DS_Store
new file mode 100644
index 0000000..6005046
Binary files /dev/null and b/app/.DS_Store differ
diff --git a/app/assets/images/.keep b/app/assets/images/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
new file mode 100644
index 0000000..1019580
--- /dev/null
+++ b/app/assets/javascripts/application.js
@@ -0,0 +1,17 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// compiled file.
+//
+// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
+// about supported directives.
+//
+//= require jquery
+//= require jquery_ujs
+//= require bootstrap
+//= require turbolinks
+//= require_tree .
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/static_pages.coffee b/app/assets/javascripts/static_pages.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/static_pages.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/urls.coffee b/app/assets/javascripts/urls.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/urls.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/application.css b/app/assets/stylesheets/application.css
new file mode 100644
index 0000000..f665f9e
--- /dev/null
+++ b/app/assets/stylesheets/application.css
@@ -0,0 +1,16 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
+ * compiled file so the styles you add here take precedence over styles defined in any styles
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
+ * file per style scope.
+ *
+ *= require_tree .
+ *= require_self
+ *=
+ */
diff --git a/app/assets/stylesheets/custom.css.scss b/app/assets/stylesheets/custom.css.scss
new file mode 100644
index 0000000..58f5433
--- /dev/null
+++ b/app/assets/stylesheets/custom.css.scss
@@ -0,0 +1,105 @@
+@import "bootstrap-sprockets";
+@import "bootstrap";
+
+$color1: #FFFFFF;
+$color2: #CCCCCC;
+$color3: #888888;
+$bootstrapBlue: #337ab7;
+
+@mixin box_sizing {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* header and footer */
+.nav-pills {
+ float: right;
+}
+
+.nav-pills a {
+ color: black;
+}
+
+header {
+ .navbar {
+ padding: 20px;
+ border: 1px solid black;
+ }
+
+ #logo {
+ float: left;
+ font-size: 2em;
+ color: black;
+ }
+
+ #logo:hover {
+ color: $color3;
+ text-decoration: none;
+ }
+
+ #loginIdentifier {
+ padding: 10px 30px 0 0;
+ }
+}
+
+footer {
+ border-top: 1px solid black;
+ padding: 0;
+ margin: 100px 0;
+ clear: both;
+}
+
+/* main content */
+h1 {
+ text-align: center;
+ margin-bottom: 20px;
+}
+
+/* index pages */
+.index-box {
+ border: 1px solid $bootstrapBlue;
+ width: 31%;
+ float: left;
+ margin: 1%;
+ padding: 10px 10px 10px 20px;
+}
+
+.catalog {
+ width: 80%;
+ margin: auto;
+
+ tr:nth-child(odd) {
+ background-color: $color1;
+ }
+
+ tr:nth-child(even) {
+ background-color: $color2;
+ }
+
+ td {
+ font-size: 16px;
+ }
+}
+
+.pagination {
+ width: 100%;
+}
+
+/* form pages*/
+input {
+ width: 100%;
+ margin-bottom: 20px;
+ @include box_sizing;
+}
+
+.formMessage {
+ width: 100%;
+ margin-top: 20px;
+ text-align: right;
+}
+
+.debug_dump {
+ margin-top: 50px;
+ @include box_sizing;
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/urls.scss b/app/assets/stylesheets/urls.scss
new file mode 100644
index 0000000..a4281ec
--- /dev/null
+++ b/app/assets/stylesheets/urls.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Urls 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
new file mode 100644
index 0000000..ec2bf30
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,6 @@
+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
+ include ApplicationHelper
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
new file mode 100644
index 0000000..b09db02
--- /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[:session][:email].downcase)
+ if user && user.authenticate(params[:session][:password])
+ log_in(user)
+ redirect_to mylinks_url
+ else
+ flash[:danger] = "Email/password mismatch"
+ redirect_to login_path
+ end
+ end
+
+ def destroy
+ if current_user != nil
+ log_out
+ end
+ redirect_to root_url
+ end
+end
diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb
new file mode 100644
index 0000000..cf48a8b
--- /dev/null
+++ b/app/controllers/static_pages_controller.rb
@@ -0,0 +1,4 @@
+class StaticPagesController < ApplicationController
+ def home
+ end
+end
diff --git a/app/controllers/urls_controller.rb b/app/controllers/urls_controller.rb
new file mode 100644
index 0000000..b1a03b9
--- /dev/null
+++ b/app/controllers/urls_controller.rb
@@ -0,0 +1,85 @@
+class UrlsController < ApplicationController
+ before_action :logged_in_user
+ before_action :correct_user, only: [:edit, :update]
+
+
+ def new
+ @url = Url.new
+ end
+
+ def create
+ @url = Url.new(url_params)
+ @url.user = current_user
+ if @url.save
+ flash[:success] = "Shortened!"
+ render 'land'
+ else
+ flash[:danger] = @url.errors.full_messages.first
+ render 'new'
+ end
+ end
+
+ def land
+ @url = Url.find(params[:id])
+ end
+
+ def index
+ @urls = Url.paginate(page: params[:page])
+ @pageTitle = "List of Links"
+ end
+
+ def myIndex
+ @urls = Url.where(user: current_user).paginate(page: params[:page])
+ @pageTitle = "My Links"
+ render 'index'
+ end
+
+ def show
+ @url = Url.find(params[:id])
+ @url.clicks += 1
+ @url.save
+ redirect_to @url.longText
+ end
+
+ def edit
+ @url = Url.find(params[:id])
+ end
+
+ def update
+ @url = Url.find(params[:id])
+ if @url.update_attributes(url_params)
+ flash.now[:success] = "Changes saved."
+ render 'land'
+ else
+ flash[:danger] = @url.errors.full_messages.first
+ render 'edit'
+ end
+ end
+
+ def destroy
+ @url = Url.find(params[:id]).destroy
+ flash[:success] = "Link deleted"
+ redirect_to urls_url
+ end
+
+ private
+ def url_params
+ params.require(:url).permit(:longText)
+ end
+
+ def logged_in_user
+ if current_user == nil
+ flash[:danger] = "Please log in."
+ redirect_to login_url
+ end
+ end
+
+ def correct_user
+ @user = Url.find(params[:id]).user
+ if current_user != @user
+ flash[:danger] = "You can only update your own links."
+ redirect_to root_url
+ end
+ end
+
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 0000000..fb82c27
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,78 @@
+class UsersController < ApplicationController
+
+ before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
+ before_action :correct_user, only: [:edit, :update]
+ before_action :admin_user, only: :destroy
+
+ def new
+ @user = User.new
+ end
+
+ def create
+ @user = User.new(user_params)
+ if @user.save
+ log_in(@user)
+ flash[:success] = "Welcome!"
+ redirect_to @user
+ else
+ flash[:danger] = @user.errors.full_messages.first
+ render 'new'
+ end
+ end
+
+ def edit
+ @user = User.find(params[:id])
+ end
+
+ def update
+ @user = User.find(params[:id])
+ if @user.update_attributes(user_params)
+ flash[:success] = "Changes saved."
+ redirect_to @user
+ else
+ flash[:danger] = @user.errors.full_messages.first
+ render 'edit'
+ end
+ end
+
+ def show
+ @user = User.find(params[:id])
+ end
+
+ def index
+ @users = User.order(:last_name).paginate(page: params[:page], per_page: 30)
+ end
+
+ def destroy
+ @user = User.find(params[:id]).destroy
+ flash[:success] = "User deleted"
+ redirect_to users_url
+ end
+
+ private
+ def user_params
+ params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
+ end
+
+ def logged_in_user
+ if current_user == nil
+ flash[:danger] = "Please log in."
+ redirect_to login_url
+ end
+ end
+
+ def correct_user
+ @user = User.find(params[:id])
+ if current_user != @user
+ flash[:danger] = "You can only update your own profile."
+ redirect_to root_url
+ end
+ end
+
+ def admin_user
+ if !current_user.admin?
+ flash[:danger] = "Only administrators can delete users"
+ redirect_to root_url
+ end
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 0000000..64a54ef
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,24 @@
+module ApplicationHelper
+
+ def full_name(user)
+ "#{user.first_name} #{user.last_name}"
+ end
+
+ def log_in(user)
+ session[:user_id] = user.id
+ end
+
+ def log_out
+ session.delete(:user_id)
+ @current_user = nil
+ end
+
+ def current_user
+ @current_user ||= User.find_by(id: session[:user_id])
+ end
+
+ def shortUrl(url)
+ "#{root_url}urls/#{url.id}"
+ end
+
+end
diff --git a/app/mailers/.keep b/app/mailers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/.keep b/app/models/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/url.rb b/app/models/url.rb
new file mode 100644
index 0000000..2ccb65e
--- /dev/null
+++ b/app/models/url.rb
@@ -0,0 +1,26 @@
+require 'uri'
+require 'net/http'
+
+class ResponseValidator < ActiveModel::Validator
+ def validate(url)
+ uri = URI.parse(url.longText)
+ response = Net::HTTP.get_response(uri)
+ unless response.code == '200'
+ url.errors[:base] << "Website response: #{response.code}"
+ end
+ end
+end
+
+class Url < ActiveRecord::Base
+
+ belongs_to :user
+
+ JOES_URL_REGEX = /\Ahttps?:\/\//
+ URL_REGEX = URI.regexp
+ validates :longText, presence: true,
+ format: {with: URL_REGEX, message: "Not a valid URI"},
+ format: {with: JOES_URL_REGEX, message: "Joe says no"}
+
+ validates_with ResponseValidator
+
+end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 0000000..b06617d
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,33 @@
+class User < ActiveRecord::Base
+
+
+ before_save { self.email = email.downcase }
+ validates :first_name, presence: true,
+ length: {maximum: 50}
+
+ validates :last_name, presence: true,
+ length: {maximum: 50}
+
+ VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
+ validates :email, presence: true,
+ length: {maximum: 255},
+ format: {with: VALID_EMAIL_REGEX},
+ uniqueness: {case_sensitive: false}
+
+ validates :password, presence: true,
+ length: {minimum: 8},
+ allow_nil: true
+
+ has_secure_password
+
+ has_many :urls
+
+ # Returns the hash digest of the given string.
+ def User.digest(string)
+ cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
+ BCrypt::Engine.cost
+ BCrypt::Password.create(string, cost: cost)
+ end
+
+
+end
diff --git a/app/views/.DS_Store b/app/views/.DS_Store
new file mode 100644
index 0000000..c3c785d
Binary files /dev/null and b/app/views/.DS_Store differ
diff --git a/app/views/layouts/_flash.html.erb b/app/views/layouts/_flash.html.erb
new file mode 100644
index 0000000..71dea0c
--- /dev/null
+++ b/app/views/layouts/_flash.html.erb
@@ -0,0 +1,5 @@
+<% flash.each do |message_type, message| %>
+
+ <%= message %>
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb
new file mode 100644
index 0000000..0105b3d
--- /dev/null
+++ b/app/views/layouts/_footer.html.erb
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb
new file mode 100644
index 0000000..2b9cb0a
--- /dev/null
+++ b/app/views/layouts/_header.html.erb
@@ -0,0 +1,41 @@
+
+
+
\ No newline at end of file
diff --git a/app/views/layouts/_listTable.html.erb b/app/views/layouts/_listTable.html.erb
new file mode 100644
index 0000000..59034a6
--- /dev/null
+++ b/app/views/layouts/_listTable.html.erb
@@ -0,0 +1,42 @@
+
\ No newline at end of file
diff --git a/app/views/layouts/_urlTable.html.erb b/app/views/layouts/_urlTable.html.erb
new file mode 100644
index 0000000..2464aa2
--- /dev/null
+++ b/app/views/layouts/_urlTable.html.erb
@@ -0,0 +1,49 @@
+
+
+
+ <%= will_paginate %>
+
+
+
+
Our Version
+
Long Version
+
Clicks
+
User
+
+
+
+
+ <% @urls.each do |url| %>
+
+
+
+ <%= shortUrl(url) %>
+
+
+ <%= url.longText %>
+
+
+ <%= url.clicks %>
+
+
+ <%= link_to full_name(url.user), url.user %>
+
+
+ <% if current_user == url.user %>
+ <%= link_to "Edit", edit_url_path(url) %>
+ <% end %>
+
+
+ <% if (current_user.admin? || current_user == url.user) %>
+ <%= link_to "Delete", url, method: :delete,
+ data: {confirm: "Really delete this url?"} %>
+ <% end %>
+
+
+
+ <% end %>
+
+
+ <%= will_paginate %>
+
+
\ No newline at end of file
diff --git a/app/views/layouts/_userBoxes.html.erb b/app/views/layouts/_userBoxes.html.erb
new file mode 100644
index 0000000..4da29c4
--- /dev/null
+++ b/app/views/layouts/_userBoxes.html.erb
@@ -0,0 +1,18 @@
+<%= will_paginate %>
+<% @users.each do |user| %>
+
+
<%= link_to full_name(user), user %>
+
<%= user.email %>
+
+ <% if user == current_user %>
+ <%= link_to "Edit", edit_user_path(current_user) %>
+ <% end %>
+ <% if current_user == user && current_user.admin? %> | <% end %>
+ <% if current_user.admin? %>
+ <%= link_to "Delete", user, method: :delete,
+ data: {confirm: "Are you sure?"} %>
+ <% end %>
+
+
+<% end %>
+<%= will_paginate %>
\ No newline at end of file
diff --git a/app/views/layouts/_userTable.html.erb b/app/views/layouts/_userTable.html.erb
new file mode 100644
index 0000000..08e45ff
--- /dev/null
+++ b/app/views/layouts/_userTable.html.erb
@@ -0,0 +1,41 @@
+
+
+
+ <%= will_paginate %>
+
+
+
+
Name
+
Email
+
+
+
+
+ <% @users.each do |user| %>
+
+
+
+ <%= link_to full_name(user), user %>
+
+
+ <%= user.email %>
+
+
+ <% if user == current_user %>
+ <%= link_to "Edit", edit_user_path(current_user) %>
+ <% end %>
+
+
+ <% if current_user.admin? %>
+ <%= link_to "Delete", user, method: :delete,
+ data: {confirm: "Really delete this user?"} %>
+ <% end %>
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb
new file mode 100644
index 0000000..2f926f5
--- /dev/null
+++ b/app/views/users/index.html.erb
@@ -0,0 +1,5 @@
+<% provide(:title, "User List") %>
+
+
User List
+
+<%= render 'layouts/userBoxes' %>
\ No newline at end of file
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
new file mode 100644
index 0000000..e6b303c
--- /dev/null
+++ b/app/views/users/new.html.erb
@@ -0,0 +1,27 @@
+<% provide(:title, "Sign up") %>
+
+
+ Already have an account?
+ <%= link_to "Log in.", login_path %>
+
+
+
+<% end %>
+
+
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
new file mode 100644
index 0000000..120bfa7
--- /dev/null
+++ b/app/views/users/show.html.erb
@@ -0,0 +1,4 @@
+<% provide(:title, full_name(@user)) %>
+
+
<%= full_name(@user) %>
+
<%= @user.email %>
\ No newline at end of file
diff --git a/bin/bundle b/bin/bundle
new file mode 100755
index 0000000..66e9889
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/rails b/bin/rails
new file mode 100755
index 0000000..4d608ed
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+begin
+ load File.expand_path("../spring", __FILE__)
+rescue LoadError
+end
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 0000000..8017a02
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+begin
+ load File.expand_path("../spring", __FILE__)
+rescue LoadError
+end
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 0000000..acdb2c1
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+require 'pathname'
+
+# path to your application root.
+APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
+
+Dir.chdir APP_ROOT do
+ # This script is a starting point to setup your application.
+ # Add necessary setup steps to this file:
+
+ puts "== Installing dependencies =="
+ system "gem install bundler --conservative"
+ system "bundle check || bundle install"
+
+ # puts "\n== Copying sample files =="
+ # unless File.exist?("config/database.yml")
+ # system "cp config/database.yml.sample config/database.yml"
+ # end
+
+ puts "\n== Preparing database =="
+ system "bin/rake db:setup"
+
+ puts "\n== Removing old logs and tempfiles =="
+ system "rm -f log/*"
+ system "rm -rf tmp/cache"
+
+ puts "\n== Restarting application server =="
+ system "touch tmp/restart.txt"
+end
diff --git a/bin/spring b/bin/spring
new file mode 100755
index 0000000..5e7ecc4
--- /dev/null
+++ b/bin/spring
@@ -0,0 +1,15 @@
+#!/usr/bin/env ruby
+
+# This file loads spring without using Bundler, in order to be fast.
+# It gets overwritten when you run the `spring binstub` command.
+
+unless defined?(Spring)
+ require "rubygems"
+ require "bundler"
+
+ if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
+ Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq }
+ gem "spring", match[1]
+ require "spring/binstub"
+ end
+end
diff --git a/config.ru b/config.ru
new file mode 100644
index 0000000..bd83b25
--- /dev/null
+++ b/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/config/application.rb b/config/application.rb
new file mode 100644
index 0000000..8de194a
--- /dev/null
+++ b/config/application.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups)
+
+module Template
+ class Application < Rails::Application
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+ # config.time_zone = 'Central Time (US & Canada)'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+ # config.i18n.default_locale = :de
+
+ # Do not swallow errors in after_commit/after_rollback callbacks.
+ config.active_record.raise_in_transactional_callbacks = true
+ end
+end
diff --git a/config/boot.rb b/config/boot.rb
new file mode 100644
index 0000000..6b750f0
--- /dev/null
+++ b/config/boot.rb
@@ -0,0 +1,3 @@
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' # Set up gems listed in the Gemfile.
diff --git a/config/database.yml b/config/database.yml
new file mode 100644
index 0000000..1c1a37c
--- /dev/null
+++ b/config/database.yml
@@ -0,0 +1,25 @@
+# SQLite version 3.x
+# gem install sqlite3
+#
+# Ensure the SQLite 3 gem is defined in your Gemfile
+# gem 'sqlite3'
+#
+default: &default
+ adapter: sqlite3
+ pool: 5
+ timeout: 5000
+
+development:
+ <<: *default
+ database: db/development.sqlite3
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ <<: *default
+ database: db/test.sqlite3
+
+production:
+ <<: *default
+ database: db/production.sqlite3
diff --git a/config/environment.rb b/config/environment.rb
new file mode 100644
index 0000000..ee8d90d
--- /dev/null
+++ b/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the Rails application.
+require File.expand_path('../application', __FILE__)
+
+# Initialize the Rails application.
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
new file mode 100644
index 0000000..b55e214
--- /dev/null
+++ b/config/environments/development.rb
@@ -0,0 +1,41 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Do not eager load code on boot.
+ config.eager_load = false
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
+
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
+
+ # Debug mode disables concatenation and preprocessing of assets.
+ # This option may cause significant delays in view rendering with a large
+ # number of complex assets.
+ config.assets.debug = true
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # Adds additional error checking when serving assets at runtime.
+ # Checks for improperly declared sprockets dependencies.
+ # Raises helpful error messages.
+ config.assets.raise_runtime_errors = true
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+end
diff --git a/config/environments/production.rb b/config/environments/production.rb
new file mode 100644
index 0000000..03845d8
--- /dev/null
+++ b/config/environments/production.rb
@@ -0,0 +1,79 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Code is not reloaded between requests.
+ config.cache_classes = true
+
+ # Eager load code on boot. This eager loads most of Rails and
+ # your application in memory, allowing both threaded web servers
+ # and those relying on copy on write to perform better.
+ # Rake tasks automatically ignore this option for performance.
+ config.eager_load = true
+
+ # Full error reports are disabled and caching is turned on.
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Enable Rack::Cache to put a simple HTTP cache in front of your application
+ # Add `rack-cache` to your Gemfile before enabling this.
+ # For large-scale production use, consider using a caching reverse proxy like
+ # NGINX, varnish or squid.
+ # config.action_dispatch.rack_cache = true
+
+ # Disable serving static files from the `/public` folder by default since
+ # Apache or NGINX already handles this.
+ config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
+
+ # Compress JavaScripts and CSS.
+ config.assets.js_compressor = :uglifier
+ # config.assets.css_compressor = :sass
+
+ # Do not fallback to assets pipeline if a precompiled asset is missed.
+ config.assets.compile = false
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
+
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ config.force_ssl = true
+
+ # Use the lowest log level to ensure availability of diagnostic information
+ # when problems arise.
+ config.log_level = :debug
+
+ # Prepend all log lines with the following tags.
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups.
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production.
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ # config.action_controller.asset_host = 'http://assets.example.com'
+
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation cannot be found).
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners.
+ config.active_support.deprecation = :notify
+
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ config.log_formatter = ::Logger::Formatter.new
+
+ # Do not dump schema after migrations.
+ config.active_record.dump_schema_after_migration = false
+end
diff --git a/config/environments/test.rb b/config/environments/test.rb
new file mode 100644
index 0000000..1c19f08
--- /dev/null
+++ b/config/environments/test.rb
@@ -0,0 +1,42 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Do not eager load code on boot. This avoids loading your whole application
+ # just for the purpose of running a single test. If you are using a tool that
+ # preloads Rails for running tests, you may have to set it to true.
+ config.eager_load = false
+
+ # Configure static file server for tests with Cache-Control for performance.
+ config.serve_static_files = true
+ config.static_cache_control = 'public, max-age=3600'
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates.
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Randomize the order test cases are executed.
+ config.active_support.test_order = :random
+
+ # Print deprecation notices to the stderr.
+ config.active_support.deprecation = :stderr
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+end
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
new file mode 100644
index 0000000..01ef3e6
--- /dev/null
+++ b/config/initializers/assets.rb
@@ -0,0 +1,11 @@
+# Be sure to restart your server when you modify this file.
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = '1.0'
+
+# Add additional assets to the asset load path
+# Rails.application.config.assets.paths << Emoji.images_path
+
+# Precompile additional assets.
+# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
+# Rails.application.config.assets.precompile += %w( search.js )
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
new file mode 100644
index 0000000..59385cd
--- /dev/null
+++ b/config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
new file mode 100644
index 0000000..7f70458
--- /dev/null
+++ b/config/initializers/cookies_serializer.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.action_dispatch.cookies_serializer = :json
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 0000000..4a994e1
--- /dev/null
+++ b/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure sensitive parameters which will be filtered from the log file.
+Rails.application.config.filter_parameters += [:password]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
new file mode 100644
index 0000000..ac033bf
--- /dev/null
+++ b/config/initializers/inflections.rb
@@ -0,0 +1,16 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
new file mode 100644
index 0000000..dc18996
--- /dev/null
+++ b/config/initializers/mime_types.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
new file mode 100644
index 0000000..0258744
--- /dev/null
+++ b/config/initializers/session_store.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.session_store :cookie_store, key: '_Template_session'
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
new file mode 100644
index 0000000..33725e9
--- /dev/null
+++ b/config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
+end
+
+# To enable root element in JSON for ActiveRecord objects.
+# ActiveSupport.on_load(:active_record) do
+# self.include_root_in_json = true
+# end
diff --git a/config/locales/en.yml b/config/locales/en.yml
new file mode 100644
index 0000000..0653957
--- /dev/null
+++ b/config/locales/en.yml
@@ -0,0 +1,23 @@
+# Files in the config/locales directory are used for internationalization
+# and are automatically loaded by Rails. If you want to use locales other
+# than English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+# I18n.t 'hello'
+#
+# In views, this is aliased to just `t`:
+#
+# <%= t('hello') %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+# I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# To learn more, please read the Rails Internationalization guide
+# available at http://guides.rubyonrails.org/i18n.html.
+
+en:
+ hello: "Hello world"
diff --git a/config/puma.rb b/config/puma.rb
new file mode 100644
index 0000000..b9b2cf6
--- /dev/null
+++ b/config/puma.rb
@@ -0,0 +1,16 @@
+workers Integer(ENV['WEB_CONCURRENCY'] || 2)
+threads_count = Integer(ENV['MAX_THREADS'] || 5)
+threads threads_count, threads_count
+
+preload_app!
+
+rackup DefaultRackup
+port ENV['PORT'] || 3000
+environment ENV['RACK_ENV'] || 'development'
+
+on_worker_boot do
+ # Worker specific setup for Rails 4.1+
+ # See: https://devcenter.heroku.com/articles/
+ # deploying-rails-applications-with-the-puma-web-server#on-worker-boot
+ ActiveRecord::Base.establish_connection
+end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
new file mode 100644
index 0000000..411bebc
--- /dev/null
+++ b/config/routes.rb
@@ -0,0 +1,17 @@
+Rails.application.routes.draw do
+
+ root 'static_pages#home'
+ get 'static_pages/home' => 'static_pages#home'
+
+ resources :users
+ get 'signup' => 'users#new'
+
+ get 'login' => 'sessions#new'
+ post 'login' => 'sessions#create'
+ delete 'logout' => 'sessions#destroy'
+
+ get 'mylinks' => 'urls#myIndex'
+ get 'urls/:id/land' => 'urls#land'
+ resources :urls
+
+end
diff --git a/config/secrets.yml b/config/secrets.yml
new file mode 100644
index 0000000..d436146
--- /dev/null
+++ b/config/secrets.yml
@@ -0,0 +1,22 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key is used for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+# You can use `rake secret` to generate a secure secret key.
+
+# Make sure the secrets in this file are kept private
+# if you're sharing your code publicly.
+
+development:
+ secret_key_base: 268e39ed09fd79a57f7de61e00fefcb515685bce00e18a9e0950ee8253cb8c5f413e50e21d80934b2dc8415db1ee3260ec98073e475e8d4cd5980aa66f9465ae
+
+test:
+ secret_key_base: 8ecacf3aed41498c2ddc38bc3b31f3220d83836a6941798e8419cd69fc6f634558d092d8994d9634f5fca241247cf55b856d1a73bf8d2d961f6212ff3c77d480
+
+# Do not keep production secrets in the repository,
+# instead read values from the environment.
+production:
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
diff --git a/db/migrate/20151018002658_create_users.rb b/db/migrate/20151018002658_create_users.rb
new file mode 100644
index 0000000..a43e068
--- /dev/null
+++ b/db/migrate/20151018002658_create_users.rb
@@ -0,0 +1,14 @@
+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.boolean :admin, default: false
+
+ t.timestamps null: false
+ end
+ add_index :users, :email, unique: true
+ end
+end
diff --git a/db/migrate/20151019231254_create_urls.rb b/db/migrate/20151019231254_create_urls.rb
new file mode 100644
index 0000000..a3708c8
--- /dev/null
+++ b/db/migrate/20151019231254_create_urls.rb
@@ -0,0 +1,11 @@
+class CreateUrls < ActiveRecord::Migration
+ def change
+ create_table :urls do |t|
+ t.string :longText
+ t.belongs_to :user
+
+ t.timestamps null: false
+ end
+ add_index :urls, :longText, unique: true
+ end
+end
diff --git a/db/migrate/20151220191144_add_clicks_column_to_url.rb b/db/migrate/20151220191144_add_clicks_column_to_url.rb
new file mode 100644
index 0000000..88c33ab
--- /dev/null
+++ b/db/migrate/20151220191144_add_clicks_column_to_url.rb
@@ -0,0 +1,5 @@
+class AddClicksColumnToUrl < ActiveRecord::Migration
+ def change
+ add_column :urls, :clicks, :integer, default: 0
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 0000000..fa25983
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,38 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 20151220191144) do
+
+ create_table "urls", force: :cascade do |t|
+ t.string "longText"
+ t.integer "user_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.integer "clicks", default: 0
+ end
+
+ add_index "urls", ["longText"], name: "index_urls_on_longText", unique: true
+
+ create_table "users", force: :cascade do |t|
+ t.string "first_name"
+ t.string "last_name"
+ t.string "email"
+ t.string "password_digest"
+ t.boolean "admin", default: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "users", ["email"], name: "index_users_on_email", unique: true
+
+end
diff --git a/db/seeds.rb b/db/seeds.rb
new file mode 100644
index 0000000..f4f969c
--- /dev/null
+++ b/db/seeds.rb
@@ -0,0 +1,19 @@
+User.create!( first_name: "Example",
+ last_name: "User",
+ email: "example@railstutorial.org",
+ password: "password",
+ password_confirmation: "password",
+ admin: true)
+
+99.times do |n|
+ name = Faker::Name.name.split(" ")
+ first_name = name[0]
+ last_name = name[1]
+ email = "example-#{n+1}@railstutorial.org"
+ password = "password"
+ User.create!(first_name: first_name,
+ last_name: last_name,
+ email: email,
+ password: password,
+ password_confirmation: password)
+end
diff --git a/lib/assets/.keep b/lib/assets/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/lib/tasks/.keep b/lib/tasks/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/log/.keep b/log/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 0000000..b612547
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,67 @@
+
+
+
+ The page you were looking for doesn't exist (404)
+
+
+
+
+
+
+
+
+
The page you were looking for doesn't exist.
+
You may have mistyped the address or the page may have moved.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/422.html b/public/422.html
new file mode 100644
index 0000000..a21f82b
--- /dev/null
+++ b/public/422.html
@@ -0,0 +1,67 @@
+
+
+
+ The change you wanted was rejected (422)
+
+
+
+
+
+
+
+
+
The change you wanted was rejected.
+
Maybe you tried to change something you didn't have access to.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/500.html b/public/500.html
new file mode 100644
index 0000000..061abc5
--- /dev/null
+++ b/public/500.html
@@ -0,0 +1,66 @@
+
+
+
+ We're sorry, but something went wrong (500)
+
+
+
+
+
+
+
+
+
We're sorry, but something went wrong.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..3c9c7c0
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/test/controllers/.keep b/test/controllers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb
new file mode 100644
index 0000000..75db968
--- /dev/null
+++ b/test/controllers/sessions_controller_test.rb
@@ -0,0 +1,9 @@
+require 'test_helper'
+
+class SessionsControllerTest < ActionController::TestCase
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+end
diff --git a/test/controllers/static_pages_controller_test.rb b/test/controllers/static_pages_controller_test.rb
new file mode 100644
index 0000000..c3f90fd
--- /dev/null
+++ b/test/controllers/static_pages_controller_test.rb
@@ -0,0 +1,11 @@
+require 'test_helper'
+
+class StaticPagesControllerTest < ActionController::TestCase
+
+ test "should get home" do
+ get :home
+ assert_response :success
+ assert_select "title", "Home | #{main_title}"
+ end
+
+end
diff --git a/test/controllers/urls_controller_test.rb b/test/controllers/urls_controller_test.rb
new file mode 100644
index 0000000..3ec143f
--- /dev/null
+++ b/test/controllers/urls_controller_test.rb
@@ -0,0 +1,19 @@
+require 'test_helper'
+
+class UrlsControllerTest < ActionController::TestCase
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should get index" do
+ get :index
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit
+ assert_response :success
+ end
+
+end
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
new file mode 100644
index 0000000..f9b7175
--- /dev/null
+++ b/test/controllers/users_controller_test.rb
@@ -0,0 +1,67 @@
+require 'test_helper'
+
+class UsersControllerTest < ActionController::TestCase
+ def setup
+ @user = users(:faker)
+ @other_user = users(:faker2)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ assert_select "title", "Sign up | #{main_title}"
+ end
+
+ test "should redirect edit when not logged in" do
+ get :edit, id: @user
+ assert_not flash.empty?
+ assert_redirected_to login_url
+ end
+
+ test "should redirect update when not logged in" do
+ patch :update, id: @user, user: { first_name: @user.first_name,
+ last_name: @user.last_name,
+ email: @user.email }
+ assert_not flash.empty?
+ assert_redirected_to login_url
+ end
+
+ test "should redirect edit when logged in as the wrong user" do
+ log_in_as(@other_user)
+ get :edit, id: @user
+ assert_not flash.empty?
+ assert_redirected_to root_url
+ end
+
+ test "should redirect update when logged in as the wrong user" do
+ log_in_as(@other_user)
+ patch :update, id: @user, user: { first_name: @user.first_name,
+ last_name: @user.last_name,
+ email: @user.email }
+ assert_not flash.empty?
+ assert_redirected_to root_url
+ end
+
+ test "should redirect index when not logged in" do
+ log_out
+ get :index
+ assert_not flash.empty?
+ assert_redirected_to login_url
+ end
+
+ test "should redirect destroy when not logged in" do
+ assert_no_difference 'User.count' do
+ delete :destroy, id: @user
+ end
+ assert_redirected_to login_url
+ end
+
+ test "should redirect destroy when logged in as a non-admin" do
+ log_in_as(@other_user)
+ assert_no_difference 'User.count' do
+ delete :destroy, id: @user
+ end
+ assert_redirected_to root_url
+ end
+
+end
diff --git a/test/fixtures/.keep b/test/fixtures/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/urls.yml b/test/fixtures/urls.yml
new file mode 100644
index 0000000..861ee7d
--- /dev/null
+++ b/test/fixtures/urls.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ text: MyString
+
+two:
+ text: MyString
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
new file mode 100644
index 0000000..8fff971
--- /dev/null
+++ b/test/fixtures/users.yml
@@ -0,0 +1,22 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+faker:
+ first_name: Fake
+ last_name: Name
+ email: fake@name.com
+ password_digest: <%= User.digest('password') %>
+ admin: true
+
+faker2:
+ first_name: Fake2
+ last_name: Name2
+ email: fake2@name2.com
+ password_digest: <%= User.digest('password') %>
+
+<% 30.times do |n| %>
+user_<%= n %>:
+ first_name: <%= "User" %>
+ last_name: <%= n %>
+ email: <%= "user-#{n}@example.com" %>
+ password_digest: <%= User.digest('password') %>
+<% end %>
\ No newline at end of file
diff --git a/test/helpers/.keep b/test/helpers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/integration/.keep b/test/integration/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/integration/site_layout_test.rb b/test/integration/site_layout_test.rb
new file mode 100644
index 0000000..22ee37c
--- /dev/null
+++ b/test/integration/site_layout_test.rb
@@ -0,0 +1,12 @@
+require 'test_helper'
+
+class SiteLayoutTest < ActionDispatch::IntegrationTest
+
+ test "layout links" do
+ get root_path
+ assert_template 'static_pages/home'
+ assert_select "a[href=?]", root_path, count: 1
+ assert_select "a[href=?]", signup_path, count: 2
+ end
+
+end
diff --git a/test/integration/users_edit_test.rb b/test/integration/users_edit_test.rb
new file mode 100644
index 0000000..148a23a
--- /dev/null
+++ b/test/integration/users_edit_test.rb
@@ -0,0 +1,42 @@
+require 'test_helper'
+
+class UsersEditTest < ActionDispatch::IntegrationTest
+
+ def setup
+ @user = users(:faker)
+ end
+
+ test "unsuccessful edit" do
+ log_in_as(@user)
+ get edit_user_path(@user)
+ assert_template 'users/edit'
+ patch user_path(@user), user: { first_name: "",
+ last_name: "",
+ email: "foo@invalid",
+ password: "foo",
+ password_confirmation: "bar" }
+ assert_not flash.empty?
+ assert_template 'users/edit'
+ end
+
+ test "successful edit" do
+ log_in_as(@user)
+ get edit_user_path(@user)
+ assert_template 'users/edit'
+ first_name = "Foo"
+ last_name = "Bar"
+ email = "foo@bar.com"
+ patch user_path(@user), user: { first_name: first_name,
+ last_name: last_name,
+ email: email,
+ password: "",
+ password_confirmation: "" }
+ assert_not flash.empty?
+ assert_redirected_to @user
+ @user.reload
+ assert_equal first_name, @user.first_name
+ assert_equal last_name, @user.last_name
+ assert_equal email, @user.email
+ end
+
+end
diff --git a/test/integration/users_index_test.rb b/test/integration/users_index_test.rb
new file mode 100644
index 0000000..f27aa9b
--- /dev/null
+++ b/test/integration/users_index_test.rb
@@ -0,0 +1,31 @@
+require 'test_helper'
+
+class UsersIndexTest < ActionDispatch::IntegrationTest
+ def setup
+ @admin = users(:faker)
+ @non_admin = users(:faker2)
+ end
+
+ test "index as admin including pagination and delete links" do
+ log_in_as(@admin)
+ get users_path
+ assert_template 'users/index'
+ assert_select 'div.pagination'
+ first_page_of_users = User.paginate(page: 1)
+ first_page_of_users.each do |user|
+ assert_select 'a[href=?]', user_path(user), text: full_name(user)
+ unless user == @admin
+ assert_select 'a[href=?]', user_path(user), text: 'Delete'
+ end
+ end
+ assert_difference 'User.count', -1 do
+ delete user_path(@non_admin)
+ end
+ end
+
+ test "index as non-admin" do
+ log_in_as(@non_admin)
+ get users_path
+ assert_select 'a', text: 'delete', count: 0
+ end
+end
diff --git a/test/integration/users_login_test.rb b/test/integration/users_login_test.rb
new file mode 100644
index 0000000..31da960
--- /dev/null
+++ b/test/integration/users_login_test.rb
@@ -0,0 +1,39 @@
+require 'test_helper'
+
+class UsersLoginTest < ActionDispatch::IntegrationTest
+
+ def setup
+ @user = users(:faker)
+ end
+
+ test "login with invalid information" do
+ get login_path
+ assert_template 'sessions/new'
+ post login_path session: {email: "", password: ""}
+ follow_redirect!
+ assert_template 'sessions/new'
+ assert_not flash.empty?
+ end
+
+ test "login with valid information followed by logout" do
+ get login_path
+ post login_path, session: { email: @user.email, password: 'password' }
+ assert_not current_user == nil
+ assert_redirected_to @user
+ follow_redirect!
+ assert_template 'users/show'
+ assert_select "a[href=?]", login_path, count: 0
+ assert_select "a[href=?]", signup_path, count: 0
+ assert_select "a[href=?]", logout_path
+ assert_select "a[href=?]", user_path(@user)
+ delete logout_path
+ assert_not current_user == nil
+ assert_redirected_to root_url
+ follow_redirect!
+ assert_select "a[href=?]", login_path
+ assert_select "a[href=?]", signup_path
+ assert_select "a[href=?]", logout_path, count: 0
+ assert_select "a[href=?]", user_path(@user), count: 0
+
+ end
+end
diff --git a/test/integration/users_signup_test.rb b/test/integration/users_signup_test.rb
new file mode 100644
index 0000000..2fb4c57
--- /dev/null
+++ b/test/integration/users_signup_test.rb
@@ -0,0 +1,31 @@
+require 'test_helper'
+
+class UsersSignupTest < ActionDispatch::IntegrationTest
+
+ test "invalid signup information" do
+ get signup_path
+ assert_no_difference 'User.count' do
+ post users_path, user: { first_name: "",
+ last_name: "",
+ email: "invalid@user,com",
+ password: "foo",
+ password_confirmation: "bar"
+ }
+ end
+ assert_template 'users/new'
+ end
+
+ test "valid signup information" do
+ get signup_path
+ assert_difference 'User.count', 1 do
+ post_via_redirect users_path, user: { first_name: "Example",
+ last_name: "User",
+ email: "user@example.com",
+ password: "password",
+ password_confirmation: "password" }
+ end
+ assert_template 'users/show'
+ assert current_user!=nil
+ end
+
+end
diff --git a/test/mailers/.keep b/test/mailers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/models/.keep b/test/models/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/models/url_test.rb b/test/models/url_test.rb
new file mode 100644
index 0000000..7bed389
--- /dev/null
+++ b/test/models/url_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class UrlTest < 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..123b5e5
--- /dev/null
+++ b/test/models/user_test.rb
@@ -0,0 +1,87 @@
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+
+ def setup
+ @user = User.new(first_name: "Todd",
+ last_name: "Green",
+ email: "todd@green.com",
+ password: "password",
+ password_confirmation: "password")
+ end
+
+ test "should be valid" do
+ assert @user.valid?
+ end
+
+ # first name
+ test "first name should be present" do
+ @user.first_name = " "
+ assert_not @user.valid?
+ end
+
+ test "first name should not be too long" do
+ @user.first_name = "a"*51
+ assert_not @user.valid?
+ end
+
+ # last name
+ test "last name should be present" do
+ @user.last_name = " "
+ assert_not @user.valid?
+ end
+
+ test "last name should not be too long" do
+ @user.last_name = "a"*51
+ assert_not @user.valid?
+ end
+
+ # email
+ test "email should be present" do
+ @user.email = " "
+ assert_not @user.valid?
+ end
+
+ test "email should not be too long" do
+ @user.email = "a"*244 + "@example.com"
+ assert_not @user.valid?
+ end
+
+ test "email validation should accept valid addresses" do
+ valid_addresses = %w[user@example.com USER@foo.COM A_US-ER@foo.bar.org
+ first.last@foo.jp alice+bob@baz.cn]
+
+ valid_addresses.each do |valid_address|
+ @user.email = valid_address
+ assert @user.valid?, "#{valid_address.inspect} should be valid"
+ end
+ end
+
+ test "email validation should reject invalid addresses" do
+ invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
+ foo@bar_baz.com foo@bar+baz.com]
+ invalid_addresses.each do |invalid_address|
+ @user.email = invalid_address
+ assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
+ end
+ end
+
+ test "email should be unique" do
+ @user2 = @user.dup
+ @user2.email.upcase!
+ @user.save
+ assert_not @user2.valid?
+ end
+
+ # password
+ test "password should be present" do
+ @user.password = @user.password_confirmation = " "
+ assert_not @user.valid?
+ end
+
+ test "password should be at least 8 characters in length" do
+ @user.password = @user.password_confirmation = "passwor"
+ assert_not @user.valid?
+ end
+
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 0000000..5af7d44
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,34 @@
+ENV['RAILS_ENV'] ||= 'test'
+require File.expand_path('../../config/environment', __FILE__)
+require 'rails/test_help'
+require "minitest/reporters"
+Minitest::Reporters.use!
+
+class ActiveSupport::TestCase
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
+ fixtures :all
+ include ApplicationHelper
+
+ def main_title
+ "Main Title"
+ end
+
+ def log_in_as(user, options = {})
+ password = options[:password] || 'password'
+ remember_me = options[:remember_me] || '1'
+ if integration_test?
+ post login_path, session: { email: user.email,
+ password: password,
+ remember_me: remember_me }
+ else
+ session[:user_id] = user.id
+ end
+ end
+
+ private
+
+ # Returns true inside an integration test.
+ def integration_test?
+ defined?(post_via_redirect)
+ end
+end
diff --git a/vendor/assets/javascripts/.keep b/vendor/assets/javascripts/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/vendor/assets/stylesheets/.keep b/vendor/assets/stylesheets/.keep
new file mode 100644
index 0000000..e69de29