本文介绍了如何在控制器规范中禁用 before_action?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的控制器规范中使用了这个:

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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-06 02:32