Skip to content

Commit

Permalink
Merge pull request #25 from kwappa/record-edit-history
Browse files Browse the repository at this point in the history
implement to record / show histories of editing user's resume
  • Loading branch information
kwappa committed Jan 21, 2015
2 parents 9bd4d0e + cd102db commit d89768c
Show file tree
Hide file tree
Showing 18 changed files with 248 additions and 13 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -14,6 +14,7 @@ gem 'haml-rails', '~> 0.7.0'
gem 'bcrypt', '~> 3.1.9'
gem 'username_not_reserved_validator'
gem 'qiita-markdown'
gem 'diffy', '~> 3.0.7'
gem 'devise', '~> 3.4.1'
gem 'omniauth', '~> 1.2.2'
gem 'compass-rails', '~> 2.0.0'
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Expand Up @@ -81,6 +81,7 @@ GEM
thread_safe (~> 0.1)
warden (~> 1.2.3)
diff-lcs (1.2.5)
diffy (3.0.7)
docile (1.1.5)
erb2haml (0.1.5)
html2haml
Expand Down Expand Up @@ -300,6 +301,7 @@ DEPENDENCIES
coveralls
database_rewinder
devise (~> 3.4.1)
diffy (~> 3.0.7)
erb2haml
factory_girl_rails
font-awesome-rails
Expand Down
10 changes: 10 additions & 0 deletions app/assets/javascripts/resume_histories.js.coffee
@@ -0,0 +1,10 @@
($ ->
showResumeHistoryDiff = (e) ->
e.preventDefault()
history = $(this).closest('tr').find('.history_data').data('history')
$('.edit_history_detail_container').html(history)

$('.show_resume_history').each((idx, elem) ->
$(elem).bind('click', showResumeHistoryDiff)
)
)
28 changes: 28 additions & 0 deletions app/assets/stylesheets/users/profile.css.scss
Expand Up @@ -50,6 +50,34 @@ table.profile {
}
}

.edit_histories {
@include clearfix;
width: 100%;

.edit_history_list {
float: left;
width: 25%;
table {
width: 90%;
margin: auto;
}
}

.edit_history_detail {
float: left;
width: 75%;
.edit_history_detail_container {
padding-left: 16px;
height: 25em;
overflow-y: auto;
}
}
}

ul.pure-paginator {
margin-bottom: 32px;
}

form.resume_form {
textarea {
width: 80%;
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/user_resumes_controller.rb
Expand Up @@ -26,7 +26,7 @@ def create
end

def update
@user_resume.update_attributes(body: user_resume_params[:body])
@user_resume.update_body(user_resume_params[:body])
flash[:notice] = 'Resume updated.'
redirect_to home_path(@user.nick)
end
Expand Down
24 changes: 17 additions & 7 deletions app/controllers/users_controller.rb
@@ -1,5 +1,8 @@
class UsersController < ApplicationController
MEMBERS_PER_PAGE = 10
MEMBERS_PER_PAGE = 10
HISTORIES_PER_PAGE = 10

before_action :prepare_user, only: [:show, :resume_histories, :resume_history]

layout 'users'

Expand All @@ -10,12 +13,6 @@ def index
end

def show
if request.path_info.start_with?('/users')
@user = current_user
else
@user = User.find_by(nick: params[:nick])
end
raise ActiveRecord::RecordNotFound unless @user
end

def list
Expand All @@ -28,7 +25,20 @@ def list
@members = relation.page(params[:page]).per(MEMBERS_PER_PAGE)
end

def resume_histories
@histories = @user.resume_histories.order(:updated_at).reverse_order.page(params[:page]).per(HISTORIES_PER_PAGE)
end

def after_edit
redirect_to home_path(current_user.nick)
end

def prepare_user
if request.path_info.start_with?('/users')
@user = current_user
else
@user = User.find_by(nick: params[:nick])
end
raise ActiveRecord::RecordNotFound unless @user
end
end
1 change: 1 addition & 0 deletions app/models/user.rb
Expand Up @@ -10,6 +10,7 @@ class User < ActiveRecord::Base
has_one :resume, class_name: 'UserResume'
has_many :user_taggings
has_many :tags, through: :user_taggings, class_name: 'UserTag'
has_many :resume_histories, class_name: 'UserResumeHistory'

devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :omniauthable
Expand Down
26 changes: 26 additions & 0 deletions app/models/user_resume.rb
Expand Up @@ -3,9 +3,35 @@ class UserResume < ActiveRecord::Base

belongs_to :user

before_create :prepare_body

after_create :record_first_diff
after_save :touch_user

def touch_user
user.touch
end

def update_body(content)
old_body = self.body
new_body = self.class.strip_and_unify_newline(content)
result = update_attributes(body: new_body)

if result
UserResumeHistory.record_diff(self.user_id, old_body, new_body)
end
result
end

def record_first_diff
UserResumeHistory.record_diff(self.user_id, '', self.body)
end

def self.strip_and_unify_newline(str)
str.strip.gsub(/\r\n|\r|\n/, "\n")
end

def prepare_body
self.body = self.class.strip_and_unify_newline(self.body)
end
end
18 changes: 18 additions & 0 deletions app/models/user_resume_history.rb
@@ -0,0 +1,18 @@
class UserResumeHistory < ActiveRecord::Base
include Renderable

belongs_to :user

def self.record_diff(user_id, old_body, current_body)
diff = Diffy::Diff.new(old_body + "\n", current_body + "\n", context: 3, include_diff_info: true).to_s
create(user_id: user_id, diff: diff)
end

def quoted_diff
<<-EOD
```diff
#{self.diff}
```
EOD
end
end
38 changes: 38 additions & 0 deletions app/views/users/resume_histories.html.haml
@@ -0,0 +1,38 @@
= content_for :header do
javascript_include_tag 'resume_histories'

%div.content.pure-u-1.pure-u-md-3-4
%div
%div.posts
%h1.content-subhead
%section.post
%header.post-header
%h2
%i.fa.fa-files-o.fa-lg
Edit Histories
%div.post-description
%div.edit_histories
%div.edit_history_list
%table.pure-table.pure-table-bordered
- @histories.each_with_index do |history, idx|
%tbody
%tr{ class: idx.odd? ? 'pure-table-odd' : '' }
%td.history_data{ data: { history: history.render(:quoted_diff)} }
= history.updated_at
%td
= link_to '#', class: 'show_resume_history' do
%i.fa.fa-file-text-o.fa-lg
%div.edit_history_detail
%div.edit_history_detail_container
= paginate @histories
%div.posts
%h1.content-subhead
%section.post
%header.post-header
%h2
%i.fa.fa-file-text.fa-lg
Resume
%div.post-description
%div.resume
- if @user.resume.present?
= @user.resume.render(:body).html_safe
4 changes: 4 additions & 0 deletions app/views/users/show.html.haml
Expand Up @@ -64,3 +64,7 @@
%div.resume
- if @user.resume.present?
= @user.resume.render(:body).html_safe
- if @user.resume_histories.present?
= link_to user_resume_histories_path do
%i.fa.fa-files-o.fa-lg
Edit Histories
7 changes: 6 additions & 1 deletion config/routes.rb
Expand Up @@ -8,16 +8,21 @@

namespace :users do
get :list
resource :user_resumes, controller: '/user_resumes', as: :resume, path: :resume
resource :user_resumes, controller: '/user_resumes', as: :resume, path: :resume, only: [:new, :edit, :create, :update]
end

resources :user_tags, only: [:index, :show]

scope ':nick' do
get '/', controller: :users, action: :show, as: :home

scope :user_tags, controller: :user_tags, as: :user_tag, path: :tag do
post :attach
delete :detach
end

scope :resume_histories, controller: :users, as: :user_resume_histories, path: :resume_histories do
get '/', action: :resume_histories
end
end
end
11 changes: 11 additions & 0 deletions db/migrate/20150120053756_user_resume_histories.rb
@@ -0,0 +1,11 @@
class UserResumeHistories < ActiveRecord::Migration
def change
create_table :user_resume_histories do |t|
t.integer :user_id, null: false
t.text :diff, null: false, default: ''
t.timestamp :updated_at, null: false
end

add_index :user_resume_histories, [:user_id, :updated_at]
end
end
10 changes: 9 additions & 1 deletion db/schema.rb
Expand Up @@ -11,7 +11,15 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20150114120333) do
ActiveRecord::Schema.define(version: 20150120053756) do

create_table "user_resume_histories", force: :cascade do |t|
t.integer "user_id", null: false
t.text "diff", default: "", null: false
t.datetime "updated_at", null: false
end

add_index "user_resume_histories", ["user_id", "updated_at"], name: "index_user_resume_histories_on_user_id_and_updated_at"

create_table "user_resumes", force: :cascade do |t|
t.integer "user_id", null: false
Expand Down
23 changes: 23 additions & 0 deletions spec/controllers/users_controller_spec.rb
Expand Up @@ -71,4 +71,27 @@
it { expect { get :show, nick: 'NOT_EXISTING_USER' }.to raise_error ActiveRecord::RecordNotFound }
end
end

describe '#resume_histories' do
let(:user) { create(:user) }
subject(:resume_histories) { get :resume_histories, nick: user.nick }

context 'without resume' do
it 'shows blank page' do
expect(resume_histories).to be_ok
expect(user.resume).to_not be_present
expect(user.resume_histories).to_not be_present
end
end

context 'with resume and histories' do
let!(:resume) { create(:user_resume, user: user) }
before { resume }
it 'shows resume and histories' do
expect(resume_histories).to be_ok
expect(user.resume).to be_present
expect(user.resume_histories).to be_present
end
end
end
end
6 changes: 6 additions & 0 deletions spec/factories/user_resume_histories.rb
@@ -0,0 +1,6 @@
FactoryGirl.define do
factory :user_resume_history do

end

end
17 changes: 17 additions & 0 deletions spec/models/user_resume_history_spec.rb
@@ -0,0 +1,17 @@
require 'rails_helper'

RSpec.describe UserResumeHistory, type: :model do
let(:user) { create(:user) }

describe '.record_diff' do
subject(:record_diff) { described_class.record_diff(user.id, 'old_body', 'new_body') }
specify { expect { record_diff }.to change { described_class.count }.from(0).to(1) }
end

describe '#quoted_diff' do
let(:diff_body) { 'diff_body' }
let(:quoted_diff_body) { "```diff\n#{diff_body}\n```\n" }
let(:diff) { build(:user_resume_history, diff: diff_body) }
specify { expect(diff.quoted_diff).to eq quoted_diff_body }
end
end

0 comments on commit d89768c

Please sign in to comment.