3

私は railstutorial.org で最新の Rails チュートリアルを行っていますが、特定の演習 ( http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-users#sec:updating_deleting_exercisesの #8) で行き詰まっています。 )。管理者が自分自身を削除できないようにするには、rspec/capybara テストを作成する必要があります。実装は機能していますが、テストを正しく機能させることができません。これが私のコードです。ここで同様の質問を見つけました: Ruby on Rails syntaxおよびhttps://getsatisfaction.com/railstutorial/topics/how_to_prevent_admin_user_from_deleting_themselves。しかし、それは古いチュートリアルであり、同じ質問ではないと思います。

spec/requests/user_pages_spec.rb の関連コードは次のとおりです。

describe "User pages" do
  subject { page }
    describe "delete links" do
      describe "as an admin user" do
        let(:admin) { FactoryGirl.create(:admin) }
        before do
          sign_in admin
          visit users_path
        end
        it "should not be able to delete themself" do
          expect { admin.delete }.should_not change(User, :count)
        end
      end
    end
  end
end

エラー メッセージには、ユーザー数が 1 減っていることが示されています。

完全を期すために、ここに私の(作業中の)実装があります:

class UsersController < ApplicationController
  before_filter :current_admin,     only: :destroy
  def current_admin
  @user = User.find(params[:id])
    redirect_to users_path, notice: "Cannot delete current admin" if current_user?(@user)
  end
end

ありがとう、どこが間違っているの?(いくつかの方法を省略しましたが、うまくいけば、私がやろうとしていることを理解するのに十分です)

編集:Ruby v1.9.3、Rails v3.2.3を使用。デフォルトでは、管理者用の削除リンクはありません。

Edit2:これが私が取り組んだものです:

仕様/コントローラー/users_controller_spec.rb

require 'spec_helper'

describe UsersController do
  describe "admins" do
    let(:admin) { FactoryGirl.create(:admin) }

    it "should not be able to delete themself" do
      sign_in admin
      expect { delete :destroy, :id => admin.id }.should_not change(User, :count)
    end
  end
end

users_controller.rb

def destroy
  @user = User.find(params[:id])

  if current_user?(@user)
    flash[:error] = "Cannot delete current admin"
  else
    @user.destroy
    flash[:success] = "User destroyed."
  end
  redirect_to users_path
end
4

2 に答える 2

7

before_filter の構文が正しくありません。呼び出しは次のようになります

before_filter :current_admin, :only => [:destroy]

おそらく、このロジックを破棄アクションに保持した方がよいでしょう。そのアクションにのみ適用されるため、別のメソッド/フィルターに移動する理由はありません。あなたが指摘した他の質問は、実際にはチュートリアルの古いバージョンのものですが、それでもロジックは同じです:

class UsersController < ApplicationController
  def destroy
    @user = User.find(params[:id])

    if current_user?(@user)
      flash[:error]  = "Cannot delete current admin"
    else
      user.destroy
      flash[:notice] = "User was successfully deleted"
    end

    redirect_to users_path
  end
end

テストに関しては、コントローラーで destroy アクションの代わりに delete メソッドを呼び出しているため、失敗しています。ActiveRecord::Relationから

Active Record オブジェクトはインスタンス化されないため、:dependent 関連オプションや Observer メソッドを含め、オブジェクトのコールバックは実行されません。

rspec/capybara を使用するよう求められているため、click_link メソッドを使用して destroy アクションをトリガーできます。複数のリストを含むインデックス ページを表示しているため、適切なボタンを確実に選択するには、Capybara::Node::Findersを調べる必要があります。

編集:ビューではなくコントローラーをテストしようとしているので、次の方法でテストできます。

describe "admins" do
  let(:admin) { FactoryGirl.create(:admin) }

   it "should not be able to delete themself" do
     sign_in admin
     expect { delete :destroy, :id => admin.id }.should_not change(User, :count)
   end
 end
于 2012-06-06T03:45:54.170 に答える
7

これは、user_pages_spec でテストできます。これは、railstutorial.org の本で求められているように思われるものです。(Ruby on Rails チュートリアルの第 9 章、演習 9)。それが良い考えであるかどうかは、より大きな心に任せます.

user_pages_spec.rb のテスト コードは次のようになります。

 describe "I should not be able to delete admins" do
      before { delete user_path(admin.id) }

      it { should_not have_selector('div.alert.alert-error', text: 'Admins cannot delete themselves') }
    end

delete user_path(admin.id) は「delete」のクリックを模倣し、rspec-capybara で動作します。これは、エラーメッセージを私のものと一致するように変更したり、その逆に変更したりすると、上記のコントローラーコードで通過します。

また、アイテムのみがある場合、UsersController の before_filter 構文は [] の有無にかかわらず機能するようです。

于 2012-11-08T15:14:29.567 に答える