2012-03-31 7 views
6

私はRubyとRailsの初心者ですから、Michael HartlのRailsチュートリアルを勉強中です。私は第9章、エクササイズ#9で立ち往生しています。これは私が管理者がログインしているときCURRENT_USERへのリンクを「削除」を追加し、ブラウザでテストするときに動作するようですRubyチュートリアルCh9演習#9 - 管理者が自分自身を削除することを許可しない

def destroy 
    user = User.find(params[:id]) 
    if (current_user == user) && (current_user.admin?) 
    flash[:error] = "Can not delete own admin account!" 
    else 
    user.destroy 
    flash[:success] = "User destroyed." 
    end 
redirect_to users_path 
end 

しかし、運動は言う:私はDEFにユーザーコントローラーのコードを破壊を更新しました。最初にテストを書く - 私はやったが、うまくいかない。ここで私はテストのために持っているものです。

describe "as admin user" do 
    let(:user_admin) { FactoryGirl.create(:admin) } 

    before { sign_in user_admin } 

    describe "submitting a DELETE request to destroy own admin account" do 
    before { delete user_path(user_admin) } 
    it { should have_selector('div.alert.alert-error', text: 'delete own admin') } 
    end 
end 

はたぶん私がテストしてい何をテストすべきではありません。ユーザーコントローラーのdef destroyコードの変更をどのようにテストしますか?

+0

私はあなたが第9章エクササイズ10を意味している可能性が信じている - 少なくともそれはそれは、今日のようにライブバージョンのように表示されるものです。 – eblume

答えて

1

私はRailsチュートリアル(および一般的なレール)も新しく、この同じ問題を抱えていて、あなたの質問は答えを見つけ出すのを助けました。

私はまだあなたのコードが失敗する理由は確かではありませんが、以下のステップは間違いなく働いています。

まず、(私はこの記述ブロックを配置する場所を残しているここに - あなたはすでに適切な場所があります)次の構造を使用するために、わずかにテストコードを変更します。私は使用しています

describe "deleting herself" do 
    it "should not be possible" do 
    expect { delete user_path(admin) }.to_not change(User, :count).by(-1) 
    end 
end 

注意を{}ブロックでUserオブジェクトの数を追跡します。これは間違いなく、テストを赤にします(これは良い点です)。フラッシュをチェックするとになりますが、エラーのフラッシュを確認することはここでは機能していません。私は本当に理由を知らない!たぶんダブルリダイレクトと何か関係がありますか?

次に、保護コードを書き、テストを再び緑色にします。あなたのコードは動作します(と思う)が、私は私のコードは、それがセッションヘルパーは、以前の第9章で定義された

def destroy 
    user = User.find(params[:id]) 
    if (current_user? user) && (current_user.admin?) 
    flash[:error] = "You are not allowed to delete yourself as an admin." 
    else 
    user.destroy 
    flash[:success] = "User destroyed. ID: #{user.id}" 
    end 
    redirect_to users_path 
end 

を使用するには、この変更は、私のテストは、再び「グリーン」行かれ作らもう少し慣用句だと思います練習10を正常に完了しました。

3

元の投稿にコードを入れようとしましたが、運がありませんでした。代わりに、私はこれのように動作するようにしました(失敗してパスしました)。適切なリダイレクトと正しいフラッシュメッセージがテストされます。

TEST:authentication_pages_spec.rb

describe "as admin user" do 
    let(:admin) { FactoryGirl.create(:admin) } 
    before { sign_in admin } 

    describe "can't delete self by submitting DELETE request to Users#destroy" do 
     before { delete user_path(admin) } 
     specify { response.should redirect_to(users_path), 
        flash[:error].should =~ /Can not delete own admin account!/i } 
    end 
    end 

実装は:道は、我々は要求を発行しているため、ユーザー#は

def destroy 
    user = User.find(params[:id]) 
    if (current_user == user) && (current_user.admin?) 
     flash[:error] = "Can not delete own admin account!" 
    else 
     user.destroy 
     flash[:success] = "User destroyed." 
    end 
    redirect_to users_path 
    end 

を破壊おそらく、元のテストが働いていなかった理由は? 私は失敗した記述ブロックし、すべてに個別に、次の各追加してみました:カピバラは実際にこれらのセレクタを確認するためにページにリダイレクトされていないよう

ので
it { should have_selector('div.alert.alert-error', text: 'delete own admin') } 

it { should have_selector('title', text: 'All users') } 
it { should have_selector('h1', text: 'All users') } 

を、と思われます。私は 'title'と 'h1'を試してみましたが、セレクタ 'div.alert.alert-error'に何らかの問題があったと思っていましたが、 'title'と 'h1' ...

specify { response.should ... }スタイルテストの詳細については誰でも知りたいですか?彼らはコントローラのアクションをヒットしたときにリダイレクトに従っていない場合は?

0

私はRailsの初心者向けのチュートリアルをやっていますが、あなたの投稿は私には大いに役立ちますが、貢献するためには、ユーザーが破壊の管理者であるかどうかを確認する必要はありません行を追加するときに管理者のみが破棄されます。

before_action :admin_user,  only: :destroy 

ユーザコントローラで破棄されます。

だから、ちょうどかどうか尋ねるために十分であるテストだけカウントが

describe "as admin user" do 
    let(:admin) { FactoryGirl.create(:admin) } 
    before { sign_in(admin) } 

    it "should not be able to delete itself" do 
    expect { delete user_path(admin) }.not_to change(User, :count) 
    end 
end 

どちらかを削除しようとした後に変更されていないことを確認する必要がありまた

def destroy 
    usertodestroy = User.find(params[:id]) 
    if (current_user == usertodestroy) 
    flash[:error] = 'Can´t delete own user' 
    else 
    usertodestroy.destroy 
    flash[:success] = "User destroyed. ID: #{usertodestroy.name}" 
    redirect_to users_url 
    end 
end 

現在のユーザーと同じではありません結果を変更することはありませんが、単純に物事を単純に保ちます。私は実際に得ることができなかったのはなぜ

次のコードは、ユーザーを削除するどのような場合には、なぜテストするときである:それは削除すべきではありませんので、私の意見で

describe "as admin user" do 
    let(:admin) { FactoryGirl.create(:admin) } 
    before { sign_in(admin) } 

    it "should not be able to delete itself" do 
    expect { admin.destroy }.not_to change(User, :count) 
    end 
end 

これはストレートがUserControllerを呼んでいます。

+0

(私はRailsの初心者くさいのだけど、数年のためのRubyを行ってき...)私は2番目のバージョンは、管理対象ではないがUserControllerインスタンスのdestroyメソッドのdestroyメソッドを呼び出していると思うし、その理由(それはですadmin)ユーザーはコントローラファイルのコードに関係なく破壊されます。 – davej

0

は、上記の提案を以下にもかかわらず、私のテストははまだがエラーで、渡しませんでした。私はこれが唯一の一部として呼び出されているためで、ロギングといくつかの問題があった意味にかかった

undefined method `admin?' for nil:NilClass 

before_filter 'admin_user'チェック。

私は方法

に感謝
before { signin admin, no_capybara: true } 

符号の非カピバラのバージョンを使用して、この問題を解決することができました!

0

私は良いためeblume提案を適用し、私もいくつかの発言と疑問を持っている:我々は、カウントが変化して一つのユニットではなく、それが変化しているかどうかを確認する必要がないよう

はまず、テストを簡略化することができ任意の番号で:

expect { delete user_path(admin) }.not_to change(User, :count) 

コントローラ内のコードについては、簡略化することもできます。ユーザーが管理者である場合は「破棄」メソッドの中にチェックする必要はありません

def admin_user 
    redirect_to(root_url) unless current_user.admin? 
end 

、それは管理者である必要があります:私たちは、破壊のために、以下の前にアクションをコード化されていたとして。

句になるのであれば:

if (current_user? user) 

私の問題は今ある:私はこのコードを理解していない、私は、このチェックは何をするか分かりません。私の最初の試みではなく、以下の使用していた

if (current_user.id == params[:id]) 

をしかし、これは動作しません、私はなぜ理解していません。

1

リスト9.43のtutorialでは、app/views/users/_user.html.erbの部分ビューには、現在ログインしている管理者の「削除」リンクが表示されないようにするチェックがありますユーザーのインデックスページに表示されます。

ウェブUIを通じて自分のアカウントを削除することはできませんが、9.9ではさらに、現在のユーザーに対してhttp削除要求を作成して送信した場合にコントローラレベルにロジックがあることを確認しています。アップトリミング任意の奇妙なバグを防ぐために、あなたのレールのアプリを中心にこれらの安全ガードを追加するための全体的な

おそらく良い練習。部分ビューのフィルタ以来

はあなたにも「他」を除去することにより、ユーザコントローラの破壊行為を簡素化することができ、それはあなたが、とにかくエラーフラッシュを見ることはないだろうことができます。私にとって

def destroy 
    user = User.find(params[:id]) 
    unless current_user?(user) 
    user.destroy 
    flash[:success] = "User deleted." 
    end 
    redirect_to users_url 
end 
+0

よく置いてください。私の知る限り、今まで起こってから「XYZ」を防ぐ行の後に「あなたはXYZすることはできません」と言ってフラッシュメッセージのショーを持っている非論理的だろう言うことができるように。 – LpLrich

0

コントローラのアクション

def destroy 
    usertodestroy = User.find(params[:id]) 
    if (current_user == usertodestroy) 
    flash[:error] = 'Can´t delete own user' 
    redirect_to root_url 
    else 
    usertodestroy.destroy 
    flash[:success] = "User destroyed. ID: #{usertodestroy.name}" 
    redirect_to users_url 
    end 
end 

とテスト

describe "as admin user" do 
    let(:admin) { FactoryGirl.create(:admin) } 
    before { sign_in admin, no_capybara: true } 

    it "attempting to delete self" do 
    expect{ delete user_path(admin) }.not_to change(User, :count) 
    end 
end 

作品。

+1

変更内容とその理由を説明できますか? – Chris

+0

サインインしているユーザーと現在のユーザーだけを比較します。それが同じ人なら、彼は自分自身を削除してroot_urlにリダイレクトすることはできません。そうでなければ、現在のユーザーはadmin:trueプロパティを持っていれば誰でも削除できます。そして、私たちはこれをチェックします(管理者は自分自身を削除できません)。 – xAgrh

関連する問題