文章目录
  1. 1. 课程目标
  2. 2. 课程复盘
    1. 2.1. 1. 首页可以按照职缺薪资下限、薪资上限、发表时间排序
      1. 2.1.1. (1)加入“下拉选单”
      2. 2.1.2. (2)在 JobsController 里面写判断式,决定要送出哪些资料
      3. 2.1.3. (3)重构重复的代码
    2. 2.2. 2. 建立投递简历的链接
    3. 2.3. 3. 产生简历 Resume 的 model
    4. 2.4. 4. 建立简历表单
    5. 2.5. 5. 加入简历上传功能 (安装 carrierwave)
      1. 2.5.1. (1)安装 carrierwave
      2. 2.5.2. (2)新增 attachment 栏位在 resume 这个 model 上
      3. 2.5.3. (3)挂上 Attachment Uploader 到 Resume 上
      4. 2.5.4. (4)修改 resume_params
    6. 2.6. 7.设计简历列表

课程目标

  • 实作 应聘者 用户故事。

应征者,可以「上传」简历用户故事细拆如下。

  • 首页可以按照职缺薪资下限排序
  • 首页可以按照职缺薪资上限排序
  • 首页可以按照职缺发表时间排序
  • 应征者可以提交自己的简历
    • 上传简历的网址应该长成这样:/jobs/1/resumes/new
    • 用户必须要登入才能提交简历
    • 简历的格式是 PDF,使用 Resume 这个 model 的 attachment 栏位
    • 上传空简历必须要被滤掉

课程复盘

1. 首页可以按照职缺薪资下限、薪资上限、发表时间排序

(1)加入“下拉选单”

修改 app/views/jobs/index.html.erb ,在

之前加入“下拉选单”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="dropdown clearfix pull-right">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenuDivider" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
排序
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuDivider">
<li>
<%= link_to("按照薪资下限排序", jobs_path(:order => "by_lower_bound")) %>
</li>
<li>
<%= link_to("按照薪资上限排序", jobs_path(:order => "by_upper_bound")) %>
</li>
<li>
<%= link_to("按照发表时间排序", jobs_path ) %>
</li>
</ul>
</div>

如此一来呢,打开 Google Chrome,右键检视 Dropdown 的 HTML,如下图所示:

这个语句

1
jobs_path(:order => "by_upper_bound")

可以生成

1
/jobs?order=by_lower_bound

这样的网址

(2)在 JobsController 里面写判断式,决定要送出哪些资料

把 JobsController 的 index 改成这样:

app/controllers/jobs_controller.rb
1
2
3
4
5
6
7
8
9
10
def index
@jobs = case params[:order]
when 'by_lower_bound'
Job.where(is_hidden: false).order('wage_lower_bound DESC')
when 'by_upper_bound'
Job.where(is_hidden: false).order('wage_upper_bound DESC')
else
Job.where(is_hidden: false).order('created_at DESC')
end
end

由 params[:order] 去决定,吐什么资料出来。

(3)重构重复的代码

app/models/job.rb
1
2
3
4
5
class Job < ApplicationRecord
...略
scope :published, -> { where(is_hidden: false) }
scope :recent, -> { order('created_at DESC') }
end

然后再修改 app/controllers/jobs_controller.rb

app/controllers/jobs_controller.rb
1
2
3
4
5
6
7
8
9
10
def index
@jobs = case params[:order]
when 'by_lower_bound'
Job.published.order('wage_lower_bound DESC')
when 'by_upper_bound'
Job.published.order('wage_upper_bound DESC')
else
Job.published.recent
end
end

2. 建立投递简历的链接

app/views/jobs/show.html.erb
1
2
3
<div class="text-center">
<%= link_to("投交履历", "#", :style => "font-size: 30px; text-decoration: underline;") %>
</div>

3. 产生简历 Resume 的 model

简历 Resume 的 Model 初步构想是,应该要跟 Job 有关,也要跟 User 有关,至少还要一个 content 栏位。所以我们可以根据这样的规划产生 model。

  • job_id:integer
  • user_id:integer
  • content:text
1
rails g model resume job_id:integer user_id:integer content:text

然后再跑

1
rake db:migrate

将 Resume 与 User / Job 连起来

app/models/resume.rb
1
2
3
4
5
6
class Resume < ApplicationRecord
...
+ belongs_to :user
+ belongs_to :job
...
end
app/models/job.rb
1
2
3
4
5
class Job < ApplicationRecord
...
+ has_many :resumes
...
end
app/models/user.rb
1
2
3
4
5
class User < ApplicationRecord
...
+ has_many :resumes
...
end

4. 建立简历表单

产生 resumes_controller

1
rails g controller resumes

修改 config/routes.rb

config/routes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Rails.application.routes.draw do
devise_for :users
namespace :admin do
resources :jobs do
member do
post :publish
post :hide
end
end
end
- resources :jobs
+ resources :jobs do
+ resources :resumes
+ end
root 'jobs#index'
end

然后修改送出简历网址为 new_job_resume_path(@job)

1
2
3
<div class="text-center">
<%= link_to("投交履历", new_job_resume_path(@job), :style => "font-size: 30px; text-decoration:underline;") %>
</div>

新增 resumes_controller 里的内容

app/controllers/resumes_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class ResumesController < ApplicationController
before_action :authenticate_user!
def new
@job = Job.find(params[:job_id])
@resume = Resume.new
end
def create
@job = Job.find(params[:job_id])
@resume = Resume.new(resume_params)
@resume.job = @job
@resume.user = current_user
if @resume.save
flash[:notice] = "成功提交履历"
redirect_to job_path(@job)
else
render :new
end
end
private
def resume_params
params.require(:resume).permit(:content)
end
end

关于redirect_to job_path(@job),重新导向至特定的job页面。

新增 app/views/resumes/new.html.erb

app/views/resumes/new.html.erb
1
2
3
4
5
6
7
8
<h3> 投交履历到 <%= @job.title %> </h3>
<hr>
<%= simple_form_for [@job, @resume] do |f| %>
<%= f.input :content %>
<%= f.submit "送出" %>
<% end %>

关于input的几个用法

简历内容不得为空

app/models/resume.rb
1
2
3
4
5
6
class Resume < ApplicationRecord
belongs_to :user
belongs_to :job
validates :content, presence: true
end

5. 加入简历上传功能 (安装 carrierwave)

(1)安装 carrierwave

Gemfile
1
gem 'carrierwave'

然后

1
bundle install

(2)新增 attachment 栏位在 resume 这个 model 上

1
rails g migration add_attachment_to_resume

内容:

1
2
3
4
5
class AddAttachmentToResume < ActiveRecord::Migration[5.0]
def change
add_column :resumes, :attachment, :string
end
end

然后

1
rake db:migrate

(3)挂上 Attachment Uploader 到 Resume 上

carrierwave 使用的是“Uploader”这个机制,因此呢,我们要

1
rails g uploader attachment

然后再修改 model,挂上去

app/models/resume.rb
1
2
3
4
5
6
7
8
class Resume < ApplicationRecord
belongs_to :user
belongs_to :job
mount_uploader :attachment, AttachmentUploader
validates :content, presence: true
end

然后修改

app/views/resumes/new.html.erb
1
2
3
4
5
6
<%= simple_form_for [@job, @resume] do |f| %>
<%= f.input :content %>
<%= f.input :attachment %>
<%= f.submit "送出" %>
<% end %>

在上传表单加入“档案上传”栏位(:attachment)。

(4)修改 resume_params

修改了表单,我们也要记得修改 resume_params,这样才能收到档案。

修改 app/controllers/resumes_controller.rb

app/controllers/resumes_controller.rb
1
2
3
4
5
6
7
8
9
def resume_params
params.require(:resume).permit(:content, :attachment)
end
```
#### (5)使用 .gitignore 屏蔽使用者产生的档案
要修改 .gitignore 这个档案,在里面记录,屏蔽掉底下所以生成的资源,避免他们被加入版本控制。
修改 .gitignore 加入:

public/uploads

1
2
3
4
5
6
### 6. admin_job_resumes_path(job)
```ruby app/views/admin/jobs/index.html.erb
- <td><%= job.resumes.count %></td>
+ <td> <%= link_to(job.resumes.count, admin_job_resumes_path(job)) %> </td>

这里的admin_job_resumes_path(job)参数为job而不是具体的变量@job,因为管理员看到的job不是特指某个job,而是所有的job,点击后该页面显示的是job下对应的所有的简历。

7.设计简历列表

依然是用form + partial的模式

1
touch app/views/admin/resumes/index.html.erb

填入

app/views/admin/resumes/index.html.erb
1
2
3
4
<h2> <%= @job.title %> - 履历列表 </h2>
<hr>
<%= render :partial => "resume", :collection => @resumes, :as => :resume %>

然后

1
touch app/views/admin/resumes/_resume.html.erb

填入

app/views/admin/resumes/_resume.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<div class="panel panel-default">
<div class="panel-heading">
<div class="row">
<div class="col-md-12">
<h3 class="panel-title">
<%= resume.user.email %>
</h3>
</div>
</div>
</div>
<div class="panel-body">
<div class="trix-content">
<p> <%= simple_format(resume.content) %> </p>
</div>
<hr>
<% if resume.attachment.present? %>
<i class="fa fa-paperclip"> </i>
<%= link_to("Download Resume", resume.attachment_url) %>
<% else %>
No Attachment
<% end %>
</div>
</div>

这里用来面板: class=”panel panel-default”

这一句最好写进helper中

1
<p> <%= simple_format(resume.content) %> </p>

固定用法: resume.attachment_url

1
2
<i class="fa fa-paperclip"> </i>
<%= link_to("Download Resume", resume.attachment_url) %>
文章目录
  1. 1. 课程目标
  2. 2. 课程复盘
    1. 2.1. 1. 首页可以按照职缺薪资下限、薪资上限、发表时间排序
      1. 2.1.1. (1)加入“下拉选单”
      2. 2.1.2. (2)在 JobsController 里面写判断式,决定要送出哪些资料
      3. 2.1.3. (3)重构重复的代码
    2. 2.2. 2. 建立投递简历的链接
    3. 2.3. 3. 产生简历 Resume 的 model
    4. 2.4. 4. 建立简历表单
    5. 2.5. 5. 加入简历上传功能 (安装 carrierwave)
      1. 2.5.1. (1)安装 carrierwave
      2. 2.5.2. (2)新增 attachment 栏位在 resume 这个 model 上
      3. 2.5.3. (3)挂上 Attachment Uploader 到 Resume 上
      4. 2.5.4. (4)修改 resume_params
    6. 2.6. 7.设计简历列表