课程目标
应征者,可以「上传」简历用户故事细拆如下。
- 首页可以按照职缺薪资下限排序
- 首页可以按照职缺薪资上限排序
- 首页可以按照职缺发表时间排序
- 应征者可以提交自己的简历
- 上传简历的网址应该长成这样:/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.rb1 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.rb1 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.rb1 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.erb1 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
|
然后再跑
将 Resume 与 User / Job 连起来
app/models/resume.rb1 2 3 4 5 6
| class Resume < ApplicationRecord ... + belongs_to :user + belongs_to :job ... end
|
app/models/job.rb1 2 3 4 5
| class Job < ApplicationRecord ... + has_many :resumes ... end
|
app/models/user.rb1 2 3 4 5
| class User < ApplicationRecord ... + has_many :resumes ... end
|
4. 建立简历表单
产生 resumes_controller
1
| rails g controller resumes
|
修改 config/routes.rb
config/routes.rb1 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.rb1 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.erb1 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.rb1 2 3 4 5 6
| class Resume < ApplicationRecord belongs_to :user belongs_to :job validates :content, presence: true end
|
5. 加入简历上传功能 (安装 carrierwave)
(1)安装 carrierwave
然后
(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
|
然后
(3)挂上 Attachment Uploader 到 Resume 上
carrierwave 使用的是“Uploader”这个机制,因此呢,我们要
1
| rails g uploader attachment
|
然后再修改 model,挂上去
app/models/resume.rb1 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.erb1 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.rb1 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.erb1 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.erb1 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) %>
|