Commit d69e6794 by Tan Phat Nguyen

Finish user edit, update, index, and destroy actions

parent 9610e719
......@@ -2,6 +2,9 @@ source 'https://rubygems.org'
gem 'rails', '4.2.0.beta4'
gem 'bcrypt', '3.1.7'
gem 'faker', '1.4.2'
gem 'will_paginate', '3.0.7'
gem 'bootstrap-will_paginate', '0.0.10'
gem 'bootstrap-sass', '3.2.0.0'
gem 'unicorn', '4.8.3'
gem 'sass-rails', '5.0.0.beta1'
......
......@@ -43,6 +43,8 @@ GEM
debug_inspector (>= 0.0.1)
bootstrap-sass (3.2.0.0)
sass (~> 3.2)
bootstrap-will_paginate (0.0.10)
will_paginate
builder (3.2.2)
byebug (3.4.0)
columnize (~> 0.8)
......@@ -63,6 +65,8 @@ GEM
debugger-linecache (1.2.0)
erubis (2.7.0)
execjs (2.2.2)
faker (1.4.2)
i18n (~> 0.5)
ffi (1.9.6)
formatador (0.2.5)
globalid (0.3.0)
......@@ -206,6 +210,7 @@ GEM
binding_of_caller (= 0.7.3.pre1)
railties (~> 4.0)
sprockets-rails (>= 2.0, < 4.0)
will_paginate (3.0.7)
PLATFORMS
ruby
......@@ -213,8 +218,10 @@ PLATFORMS
DEPENDENCIES
bcrypt (= 3.1.7)
bootstrap-sass (= 3.2.0.0)
bootstrap-will_paginate (= 0.0.10)
byebug (= 3.4.0)
coffee-rails (= 4.0.1)
faker (= 1.4.2)
guard-minitest (= 2.3.1)
jbuilder (= 2.2.3)
jquery-rails (= 4.0.0.beta2)
......@@ -234,3 +241,4 @@ DEPENDENCIES
uglifier (= 2.5.3)
unicorn (= 4.8.3)
web-console (= 2.0.0.beta3)
will_paginate (= 3.0.7)
......@@ -194,3 +194,15 @@ input {
width: auto;
margin-left: 0;
}
/* Users index */
.users {
list-style: none;
margin: 0;
li {
overflow: auto;
padding: 10px 0;
border-bottom: 1px solid $gray-lighter;
}
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ class SessionsController < ApplicationController
# Log the user in and redirect to the user's show page.
log_in user
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
redirect_to user
redirect_back_or user
else
flash.now[:danger] = "Invalid email/password combination"
render 'new'
......
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 index
@users = User.paginate(page: params[:page])
end
def show
@user = User.find(params[:id])
end
......@@ -16,7 +25,44 @@ class UsersController < ApplicationController
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] = "Profile updated"
redirect_to @user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
......@@ -37,4 +37,19 @@ module SessionsHelper
cookies.delete(:user_id)
cookies.delete(:remember_token)
end
def current_user?(user)
user == current_user
end
# Redirects to stored location (or to the default).
def redirect_back_or(default)
redirect_to(session[:forwarding_url] || default)
session.delete(:forwarding_url)
end
# Stores the URL trying to be accessed.
def store_location
session[:forwarding_url] = request.url if request.get?
end
end
......@@ -7,17 +7,17 @@ class User < ActiveRecord::Base
validates :email, presence: true, length: {maximum: 255}, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false}
validates :password, length: {minimum: 6}
validates :password, length: {minimum: 6}, allow_blank: true
has_secure_password
def User.digest(string)
def self.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
def User.new_token
def self.new_token
SecureRandom.urlsafe_base64
end
......
......@@ -6,14 +6,14 @@
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<% if logged_in? %>
<li><%= link_to "Users", "#" %></li>
<li><%= link_to "Users", users_path %></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", "#" %></li>
<li><%= link_to "Settings", edit_user_path(current_user) %></li>
<li class="divider"></li>
<li><%= link_to "Log out", logout_path, method: "delete" %></li>
</ul>
......
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</li>
\ No newline at end of file
<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.text_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %>
<div class="gravatar_edit">
<%= gravatar_for @user %>
<a href="http://gravatar.com/emails" target=_blank>change</a>
</div>
</div>
</div>
\ No newline at end of file
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= will_paginate %>
<ul class="users">
<%= render @users %>
</ul>
<%= will_paginate %>
\ No newline at end of file
Rails.application.routes.draw do
get 'sessions/new'
get 'users/new'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
......
class AddAdminToUsers < ActiveRecord::Migration
def change
add_column :users, :admin, :boolean, default: false
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141106014947) do
ActiveRecord::Schema.define(version: 20141106073354) do
create_table "users", force: true do |t|
t.string "name"
......@@ -20,6 +20,7 @@ ActiveRecord::Schema.define(version: 20141106014947) do
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.boolean "admin", default: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
......
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)
User.create!(name: "Example User",
email: "example@railstutorial.org",
password: "foobar",
password_confirmation: "foobar",
admin: true)
99.times do |n|
name = Faker::Name.name
email = "example-#{n+1}@railstutorial.org"
password = "password"
User.create!(name: name,
email: email,
password: password,
password_confirmation: password)
end
\ No newline at end of file
......@@ -5,5 +5,4 @@ class SessionsControllerTest < ActionController::TestCase
get :new
assert_response :success
end
end
......@@ -2,12 +2,61 @@ require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
@base_title = "Ruby on Rails Tutorial Sample App"
@user = users(:michael)
@other_user = users(:archer)
end
test "should get new" do
get :new
assert_response :success
assert_select 'title', "Sign up | #{@base_title}"
assert_select 'title', "Sign up | Ruby on Rails Tutorial Sample App"
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: { name: @user.name, email: @user.email }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect edit when logged in as wrong user" do
log_in_as(@other_user)
get :edit, id: @user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(@other_user)
patch :update, id: @user, user: { name: @user.name, email: @user.email }
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect index when not logged in" do
get :index
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
......@@ -2,3 +2,26 @@ michael:
name: Michael Example
email: michael@example.com
password_digest: <%= User.digest('password') %>
admin: true
archer:
name: Sterling Archer
email: duchess@example.gov
password_digest: <%= User.digest('password') %>
lana:
name: Lana Kane
email: hands@example.gov
password_digest: <%= User.digest('password') %>
mallory:
name: Mallory Archer
email: boss@example.gov
password_digest: <%= User.digest('password') %>
<% 30.times do |n| %>
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}@example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
\ No newline at end of file
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "unsuccessful edit" do
log_in_as(@user)
get edit_user_path(@user)
assert_template 'users/edit'
patch user_path(@user), user: { name: "",
email: "foo@invalid",
password: "foo",
password_confirmation: "bar" }
assert_template 'users/edit'
end
test "successful edit" do
log_in_as(@user)
get edit_user_path(@user)
assert_template 'users/edit'
name = "Foo Bar"
email = "foo@bar.com"
patch user_path(@user), user: { name: name,
email: email,
password: "",
password_confirmation: "" }
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal @user.name, name
assert_equal @user.email, email
end
test "successful edit with friendly forwarding" do
get edit_user_path(@user)
log_in_as(@user)
assert_redirected_to edit_user_path(@user)
name = "Foo Bar"
email = "foo@bar.com"
patch user_path(@user), user: { name: name,
email: email,
password: "foobar",
password_confirmation: "foobar" }
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal @user.name, name
assert_equal @user.email, email
end
end
require 'test_helper'
class UsersIndexTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
@admin = users(:michael)
@non_admin = users(:archer)
end
test "index including pagination" do
log_in_as(@user)
get users_path
assert_template 'users/index'
assert_select 'div.pagination'
User.paginate(page: 1).each do |user|
assert_select 'a[href=?]', user_path(user), text: user.name
end
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: user.name
unless user == @admin
assert_select 'a[href=?]', user_path(user), text: 'delete',
method: :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
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment