2016-12-24 15 views
0

のために私は、私のアプリのテストを機能させようとしているRailsのコースで働いています。私は、RspecがDevise(CanCanCan)と連携するために必要なヘルパーを使用していないことを示すような問題にぶつかっています。Rails 5機能テスト(Rspec/Deviseの競合?)NoMethodError:未定義メソッドadmin? #<ユーザ

以下のレポにリンクしてください。私はかなり新しい開発者ですが、読みやすくするために努力しています。ありがとうございました。

問題は私のusers_controller_spec.rbファイルから来ている:研究では

Failures: 

    1) UsersController GET #show User is logged in loads correct user details 
Failure/Error: if user&.admin? 

NoMethodError: 
    undefined method `admin?' for #<User:0x00000005c08eb0> 
# ./app/models/ability.rb:14:in `initialize' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `new' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `current_ability' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:342:in `authorize!' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:49:in `authorize_resource' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:34:in `load_and_authorize_resource' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:10:in `block in add_before_action' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/template_assertions.rb:61:in `process' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `block in process' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `catch' 
# /home/scorpian55/.rvm/gems/ruby-2[email protected]/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `_catch_warden' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `process' 
# /home/scorpian55/.rvm/gems/[email protected]/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/integration.rb:12:in `block (2 levels) in <module:Integration>' 
# ./spec/controllers/users_controller_spec.rb:15:in `block (4 levels) in <top (required)>' 

Finished in 0.36791 seconds (files took 4.43 seconds to load) 
7 examples, 1 failure 

Failed examples: 

rspec ./spec/controllers/users_controller_spec.rb:14 # UsersController GET #show User is logged in loads correct user details 

、私が見た中で最もエラーがnilのためNoMethodErrorの周りされている:NilClassと私は同じエラーを取得していないです、つまり別の問題であり、まったく同じエラーメッセージではありません。

は、私がチェックしました:

1)スペック/ rails_helper.rbがあります

config.include Devise::Test::ControllerHelpers, :type => :controller 

2)指定/ spec_helper.rbがあります

require 'spec_helper' 
require 'rspec/rails' 
# note: require 'devise' after require 'rspec/rails' 
require 'devise' 

RSpec.configure do |config| 
    config.include Devise::Test::ControllerHelpers, :type => :controller 
end 

ごと:https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)#controller-specs

関連ファイル(と私のレポ:https://github.com/ScorpIan555/gitwork):

users_controller_spec.rb

require 'rails_helper' 

describe UsersController, :type => :controller do 

let(:user) { User.create!(email: "user#{rand(100000).to_s}@examples.com", password: '1234567890') } 

    describe 'GET #show' do 

context 'User is logged in' do 
    before do 
    sign_in user 
    end 

    it 'loads correct user details' do 
    get :show, id: user.id 
    expect(response).to have_http_status(200) 
    expect(assigns(:user)).to eq user 
    end 

end #end of first context 

context 'No user is logged in' do 
    it 'redirects to login' do 
    get :show, id: user.id 
    expect(response).to redirect_to(new_user_session_path) 
    end 
end 

    end #end of GET#show block 

end #end of whole block 

ability.rb:

class Ability 
    include CanCan::Ability 

    def initialize(user) 

# Define abilities for the passed in user here. For example: 
# 
user ||= User.new # guest user (not logged in) 

alias_action :create, :read, :update, :destroy, to: :crud 

can :manage, User, id: user.id 

    if user&.admin? 

    can :crud, Product 
    can :crud, User 
    can :crud, Comment 

    elsif user&.signed_in? 

    can :read, Comment 
    can :create, Comment 
    can :read, Product 
    #can :invite, :User 

    else 
    can :read, Comment 
    can :read, Product 

    end #end if/else 
    end #end def initialize(user) 
end #end class Ability 

users_controller.rb:

class UsersController < ApplicationController 
    before_action :set_user, only: [:show, :edit, :update, :destroy] 
    before_action :authenticate_user! 
    load_and_authorize_resource 

    # GET /users 
    # GET /users.json 
    def index 
    @users = User.all 
    end 

    # GET /users/1 
    # GET /users/1.json 
    def show 
    end 

    # GET /users/new 
    def new 
    @user = User.new 
    end 

    # GET /users/1/edit 
    def edit 
    end 

    # POST /users 
    # POST /users.json 
    def create 
    @user = User.new(user_params) 

    respond_to do |format| 
     if @user.save 
     format.html { redirect_to @user, notice: 'User was  successfully created.' } 
     format.json { render :show, status: :created, location: @user } 
     else 
     format.html { render :new } 
    format.json { render json: @user.errors, status: :unprocessable_entity } 
    end 
end 
    end 

    # PATCH/PUT /users/1 
    # PATCH/PUT /users/1.json 
    def update 
respond_to do |format| 
    if @user.update(user_params) 
    format.html { redirect_to @user, notice: 'User was successfully updated.' } 
    format.json { render :show, status: :ok, location: @user } 
    else 
    format.html { render :edit } 
    format.json { render json: @user.errors, status: :unprocessable_entity } 
    end 
end 
    end 

    # DELETE /users/1 
    # DELETE /users/1.json 
    def destroy 
    @user.destroy 
    respond_to do |format| 
     format.html { redirect_to users_url, notice: 'User was successfully destroyed.' } 
     format.json { head :no_content } 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
def set_user 
    @user = User.find(params[:id]) 
end 

# Never trust parameters from the scary internet, only allow the white list through. 
def user_params 
    params.require(:user).permit(:first_name, :last_name) 
end 
end 

SCH

ActiveRecord::Schema.define(version: 20161219012011) do 

    create_table "comments", force: :cascade do |t| 
t.integer "user_id" 
t.text  "body" 
t.integer "rating" 
t.integer "product_id" 
t.datetime "created_at", null: false 
t.datetime "updated_at", null: false 
t.index ["product_id"], name: "index_comments_on_product_id" 
t.index ["user_id"], name: "index_comments_on_user_id" 
    end 

    create_table "orders", force: :cascade do |t| 
t.integer "user_id" 
t.integer "product_id" 
t.float "total" 
t.index ["product_id"], name: "index_orders_on_product_id" 
t.index ["user_id"], name: "index_orders_on_user_id" 
    end 

    create_table "products", force: :cascade do |t| 
t.string "name" 
t.text  "description" 
t.string "image_url" 
t.datetime "created_at", null: false 
t.datetime "updated_at", null: false 
t.string "color" 
t.decimal "price" 
    end 

    create_table "users", force: :cascade do |t| 
t.string "first_name" 
t.string "last_name" 
t.datetime "created_at",       null: false 
t.datetime "updated_at",       null: false 
t.string "email",     default: "", null: false 
t.string "encrypted_password",  default: "", null: false 
t.string "reset_password_token" 
t.datetime "reset_password_sent_at" 
t.datetime "remember_created_at" 
t.integer "sign_in_count",   default: 0, null: false 
t.datetime "current_sign_in_at" 
t.datetime "last_sign_in_at" 
t.string "current_sign_in_ip" 
t.string "last_sign_in_ip" 
t.boolean "admin",     default: false, null: false 
t.index ["email"], name: "index_users_on_email", unique: true 
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true 
    end 

user.rb

class User < ApplicationRecord 
    # Include default devise modules. Others available are: 
    # :confirmable, :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable 

    has_many :orders 
    has_many :comments #added troubleshooting 6.3, need to test 

end 
+0

あなたがload_and_aut 'の定義を投稿することができます:

user&.admin? 

&文字は、基本的には、ユーザーがに相当ゼロでない場合は、これを試すだけ言っていますhorize_resource'? – 31piy

+0

申し訳ありませんが、どこで見つけることができますか?私はそれがGemを正しくインストールした後に使用できることをDeviseが定義したヘルパーだと思っていました。 – ScorpIan

+0

これは私がRyan Batesのgithubで見つけたものです:https://github.com/ryanb/cancan/wiki/authorizing-controller-actions – ScorpIan

答えて

0

ema.dbあなたのコードが間違って明白なことは何もありませんでしたので、私はあなたのレポを取得し、宝石をインストールし、DBを実行した後:セットアップ私は、ことがわかりました私はあなたのエラーを複製しました。

あなたの質問に投稿されたスキーマのスキーマはわかりませんが、データベースが使用しているスキーマはわかりません。レポでの一つは、それに管理ブール値を持っていない:

create_table "users", force: :cascade do |t| 
    t.string "first_name" 
    t.string "last_name" 
    t.datetime "created_at",        null: false 
    t.datetime "updated_at",        null: false 
    t.string "email",     default: "", null: false 
    t.string "encrypted_password",  default: "", null: false 
    t.string "reset_password_token" 
    t.datetime "reset_password_sent_at" 
    t.datetime "remember_created_at" 
    t.integer "sign_in_count",   default: 0,  null: false 
    t.datetime "current_sign_in_at" 
    t.datetime "last_sign_in_at" 
    t.string "current_sign_in_ip" 
    t.string "last_sign_in_ip" 
    t.index ["email"], name: "index_users_on_email", unique: true 
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true 
    end 

私はあなたがが、その列を追加するには、移行を持っていることに注意してください。どういうわけか、移行とスキーマの同期が外れています(移行後に以前のスキーマに戻った可能性があります)。移行に

rails g migration add_admin_flag_to_users --force 

編集し、以下を追加します:

add_column :users, :admin, :boolean, default: false, null: false 

実行rails db:migraterails db:migrate RAILS_ENV=test

以下が動作するようになりまし行うための最善のことは、その列を追加し、あなたの移行を再作成することです:

$ rails c 
Running via Spring preloader in process 60107 
Loading development environment (Rails 5.0.0.1) 
2.3.1 :001 > user = User.new 
=> #<User id: nil, first_name: nil, last_name: nil, created_at: nil, updated_at: nil, email: "", admin: false> 
2.3.1 :002 > user.admin? 
=> false 
2.3.1 :003 > 

注:あなたのテストは引き続き検証に失敗しますが、それは完全に別の問題です。この障害を過ぎたので調査することができます:)

ちなみに、nilクラスのNoMethodErrorが発生した研究では、コードはそのに対して保護されています:

user.admin? if user 
+0

ありがとう@David、私は同じことに気がついた、細部への注意のおかげで、私はまだレポにコミットしていなかった。私はそれがどのようにファイルから削除された可能性がまだ分かっていないが、私はそれが何らかの事故でそれをやったに違いないb/c私はいつもそのフィールドに触れないことを知っている。最終的には、RspecはDeviseからのその方法を見ていないので、ブレークがどこにあるのか把握して修正する必要があります!ご協力いただきありがとうございます。 – ScorpIan

+0

@IanDaley - 「最終的には、Rspecがそのメソッドを見ていない」という発言に従っているかどうかわかりません...あなたのテストフレームワークで問題を再現し、修正を加えて動作させました。 )。そのメソッドはdeviesから来ていません(あなたが 'user.admin? 'を参照している場合) - railsはデフォルトであなたのモデルのブール型データベースフィールドのアクセサを生成します。 '管理者'が表示されますメソッドを呼び出します。あなたの問題は、データベースに存在しないそのフィールドから来ているだけです。 – David

+0

申し訳ありませんが、私は私の意見を誤解しました、私は別のものをタイプしている間に1つのことを考えていました!申し訳ありませんが、Railsでもまだまだ新しいものです。変わった点は、管理フィールドが存在しない唯一の場所がschema.rbであることです。しかし、私が帰ったら、強制的に移行を試みようとしています。私の人生のために、私はそれがどのように削除されたのか想像することはできませんが、あなたが指摘したように、移行はそこにあり、私はコンソールなどからフィールド上で照会することができました – ScorpIan

関連する問題