问题描述
我在我的控制器规范中使用了这个:
I've employed the use of this in my controller spec:
controller.class.skip_before_action
具体来说,在这种情况下:
Specifically, in this case:
controller.class.skip_before_action :require_authorisation_to_view_materials
controller.class.skip_before_action :require_authorisation_to_view_materials
材料控制器:
class MaterialsController < ApplicationController
before_action :set_material, only: [:show, :edit, :update, :destroy]
before_action :require_authorisation_to_view_materials, only: [:index, :show]
def require_authorisation_to_view_materials # For Materials Page
unless user_signed_in? && current_user.can_view_materials?
redirect_to root_path, alert: "You are not authorised to view the Materials page."
end
end
# GET /materials
# GET /materials.json
def index
@materials = Material.all
end
# GET /materials/1
# GET /materials/1.json
def show
end
# GET /materials/new
def new
@material = Material.new
end
# GET /materials/1/edit
def edit
end
# POST /materials
# POST /materials.json
def create
@material = Material.new(material_params)
respond_to do |format|
if @material.save
format.html { redirect_to materials_path, notice: 'Material was successfully created.' }
format.json { render :show, status: :created, location: @material }
else
format.html { render :new }
format.json { render json: @material.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /materials/1
# PATCH/PUT /materials/1.json
def update
respond_to do |format|
if @material.update(material_params)
format.html { redirect_to materials_path, notice: 'Material was successfully updated.' }
format.json { render :show, status: :ok, location: @material }
else
format.html { render :edit }
format.json { render json: @material.errors, status: :unprocessable_entity }
end
end
end
# DELETE /materials/1
# DELETE /materials/1.json
def destroy
@material.destroy
respond_to do |format|
format.html { redirect_to materials_url, notice: 'Material was successfully deleted.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_material
@material = Material.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def material_params
params.require(:material).permit(:title, :level, :description, :link)
end
end
以及完整的 materials_controller_spec:
And the full materials_controller_spec:
require "rails_helper.rb"
describe MaterialsController do
before :each do
controller.class.skip_before_action :require_authorisation_to_view_materials
end
after :each do
controller.class.before_action :require_authorisation_to_view_materials
end
describe "GET #index" do
it "populates an array of materials (@materials)" do
material1, material2 = (FactoryGirl.create :material), (FactoryGirl.create :material)
get :index
expect(assigns(:materials)).to eq([material1, material2])
end
it "renders the index view" do
get :index
expect(response).to render_template :index
end
end
describe "GET #show" do
it "assigns the requested material to @material" do
material = FactoryGirl.create :material
get :show, id: material
expect(assigns(:material)).to eq(material)
end
it "renders the #show view" do
get :show, id: FactoryGirl.create(:material)
expect(response).to render_template :show
end
end
describe "POST #create" do
context "with VALID attributes" do
it "creates new material" do
expect {
post :create, material: FactoryGirl.attributes_for(:material)
}.to change(Material, :count).by(1)
end
it "redirects to the materials page" do
post :create, material: FactoryGirl.attributes_for(:material)
expect(response).to redirect_to :materials
end
end
context "with INvalid attributes" do
it "does not create new material" do
expect {
post :create, material: FactoryGirl.attributes_for(:invalid_material)
}.to_not change(Material, :count)
end
it "re-renders the #new method" do
post :create, material: FactoryGirl.attributes_for(:invalid_material)
expect(response).to render_template :new
end
end
end
describe "PUT #update" do
before :each do
@material = FactoryGirl.create :material, title: "Title", level: "B2", description: "blah blah", link: "Dropbox Link"
end
context "valid attributes" do
it "locates the requested @material" do
put :update, id: @material, material: FactoryGirl.attributes_for(:material)
expect(assigns :material).to eq @material
end
it "changes @material's attributes" do
put :update, id: @material,
material: FactoryGirl.attributes_for(:material, title: "Title", level: "A1", description: "blah blah", link: "Dropbox Link")
@material.reload
expect(@material.title).to eq("Title")
expect(@material.level).to eq("A1")
expect(@material.description).to eq("blah blah")
end
it "redirects to the materials page" do
put :update, id: @material, material: FactoryGirl.attributes_for(:material)
expect(response).to redirect_to :materials
end
end
context "invalid attributes" do
it "locates the requested @material" do
put :update, id: @material, material: FactoryGirl.attributes_for(:invalid_material)
expect(assigns :material).to eq @material
end
it "does not change @material's attributes" do
put :update, id: @material,
material: FactoryGirl.attributes_for(:material, title: nil, level: "B1", description: "description", link: "Dropbox Link")
@material.reload
expect(@material.title).to eq("Title")
expect(@material.level).to_not eq("B1")
expect(@material.description).to eq("blah blah")
end
it "re-renders the edit method" do
put :update, id: @material, material: FactoryGirl.attributes_for(:invalid_material)
expect(response).to render_template :edit
end
end
end
describe "DELETE destroy" do
before :each do
@material = FactoryGirl.create :material
end
it "deletes the material" do
expect{
delete :destroy, id: @material
}.to change(Material, :count).by(-1)
end
it "redirects to materials#index" do
delete :destroy, id: @material
expect(response).to redirect_to :materials
end
end
end
你能看出这有什么问题吗?我实际上不明白controller.class.skip_before_action :require_authorisation_to_view_materials有效,而且我在使用它之前发生了一些奇怪的事情(但我不确定这是否应该受到指责).有人能解释一下这条线到底是做什么的吗,如果我的
Can you see anything wrong with this? I don't actually understand how the controller.class.skip_before_action :require_authorisation_to_view_materialsworks, and I've had some weird things happen before when using this (but I'm not sure if this was to blame). Could someone explain what this line does exactly, and if my
controller.class.before_action :require_authorisation_to_view_materials
在materials_controller 中切换"before_action 'back on' 真的有预期的效果吗?我的规范代码看起来没问题吗?
does actually have the intended effect of 'switching' the before_action 'back on' in the materials_controller? Does my spec code look ok?
推荐答案
在进行控制器规范和伪造登录时,我喜欢使用期望来代替授权.
When doing controller specs and faking login I like to use an expectation to stub out authorisation instead.
即在您的情况下:
require "rails_helper.rb"
describe MaterialsController do
before :each do
allow(controller).to receive(:require_authorisation_to_view_materials).and_return(true)
end
#..snip
end
甚至更好
require "rails_helper.rb"
describe MaterialsController do
before :each do
allow(controller).to receive(:current_user).and_return(FactoryGirl.create(:admin_user)
end
#..snip
end
这篇关于如何在控制器规范中禁用 before_action?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!