使用者新增 course 的話,必須要跟 user 做關聯

首先幫 context "when course has title" do 場景新增一支測試:

describe "POST create" do
  let(:user) { create(:user) }
  before { sign_in user }

  context "when course doesn't have title" do
    ...
  end

  context "when course has title" do
    ...

    it "redirects to courses_path" do
      ...
    end

    it "creates a course for user" do
      course = build(:course)

      post :create, params: { course: attributes_for(:course) }

      expect(Course.last.user).to eq(user)
    end
  end
end

錯誤訊息

$ rspec spec/controllers/courses_controller_spec.rb
...........F..........

Failures:

  1) CoursesController POST create when course has title creates a course for user
     Failure/Error: expect(Course.last.user).to eq(user)

     NoMethodError:
       undefined method `user' for #<Course:0x007fba9f993110>

Finished in 0.22045 seconds (files took 1.94 seconds to load)
22 examples, 1 failure

Course 跟 user 還沒有關聯(Association)存在。

先新增一個關聯的測試,使用 Shoulda Matchers 的 belong_to

修改 spec/modes/course_spec.rb

RSpec.describe Course do
  it { is_expected.to validate_presence_of(:title) }
  it { is_expected.to belong_to(:user) }
end

跑測試:

$ rspec spec/models/course_spec.rb
.F

Failures:

  1) Course should belong to user
     Failure/Error: it { is_expected.to belong_to(:user) }
       Expected Course to have a belongs_to association called user (no association called user)

Finished in 0.02089 seconds (files took 1.98 seconds to load)
2 examples, 1 failure

接著加上關聯。

修改 app/modesl/course.rb

class Course < ActiveRecord::Base
  belongs_to :user
  validates :title, presence: true
end
$ rspec spec/models/course_spec.rb
.F

Failures:

  1) Course should belong to user
     Failure/Error: it { is_expected.to belong_to(:user) }
       Expected Course to have a belongs_to association called user (Course does not have a user_id foreign key.)
     # ./spec/models/course_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.02253 seconds (files took 1.72 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/models/course_spec.rb:5 # Course should belong to user

缺少外鍵 user_id

新增 migration

$ rails g migration add_user_id_to_courses

class AddUserIdToCourses < ActiveRecord::Migration[5.0]
  def change
    add_column :courses, :user_id, :integer
    add_index :courses, :user_id
  end
end

通常加上外鍵時會順便加上 index,加快取得關聯物件的速度。

執行 rake db:migrate 遷移數據庫。

Model 的 spec 跑通了:

$ rspec spec/models/course_spec.rb
..

Finished in 0.01558 seconds (files took 1.67 seconds to load)
2 examples, 0 failures

course factory 補上 user

接著跑 controller spec 發現錯誤全都是:

Failure/Error: course = create(:course)

      ActiveRecord::RecordInvalid:
        Validation failed: User must exist

這是因為現在 course 需要 user 才可以創建,補上 user 到 Course Factory:

diff --git a/spec/factories.rb b/spec/factories.rb
index 54f2595..07911dc 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -10,5 +10,6 @@ FactoryGirl.define do
   factory :course do
     title "Course Name"
     description "Description."
+    user
   end
 end

加上 userfactory :course do 區塊。

再次執行測試可以看到只剩下三個錯誤:

$ rspec spec/controllers/courses_controller_spec.rb
.........FFF..........

Failures:

  1) CoursesController POST create when course has title create a new course record
     Failure/Error:
       expect do
         post :create, params: { course: attributes_for(:course) }
       end.to change { Course.count }.by(1)

       expected result to have changed by 1, but was changed by 0

  2) CoursesController POST create when course has title redirects to courses_path
     Failure/Error: expect(response).to redirect_to courses_path
       Expected response to be a <3XX: redirect>, but was a <200: OK>

  3) CoursesController POST create when course has title creates a course for user
     Failure/Error: expect(Course.last.user).to eq(user)

     NoMethodError:
       undefined method `user' for nil:NilClass

Finished in 0.29536 seconds (files took 1.69 seconds to load)
22 examples, 3 failures

創建 course 時少給了 user,在 Controller 補上。

修改 app/controller/courses_controller.rb 中的 create

diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index eb61256..3e440da 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -15,6 +15,7 @@ class CoursesController < ApplicationController

   def create
     @course = Course.new(course_params)
+    @course.user = current_user

     if @course.save
       redirect_to courses_path

補上 @course.user = current_user 即可。

results matching ""

    No results matching ""