我正在通过轨道课程工作,试图测试我的应用程序。我遇到了一个问题,似乎表明RSPEC没有使用它与Devise(Cancancan)一起使用的助手。
链接到下面的回购。我是一个相当新的开发人员,但努力使其可读。谢谢,所有的反馈都感谢。
问题来自我的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/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `new'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `current_ability'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:342:in `authorize!'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:49:in `authorize_resource'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:34:in `load_and_authorize_resource'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:10:in `block in add_before_action'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/template_assertions.rb:61:in `process'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `block in process'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `catch'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `_catch_warden'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `process'
# /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/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:nil:nilclass和我没有遇到的错误,这是一个不同的问题,而不是完全相同的错误消息。
,这是一个不同的问题。我已经检查了:
1)spec/rails_helper.rb具有:
config.include Devise::Test::ControllerHelpers, :type => :controller
2)spec/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
per:https://github.com/plataformatec/devise/wiki/wiki/how-to:test-controllers-with-rails-3-and-4-->>
这是相关文件(以及我的回复:https://github.com/scorpian5555/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
能力.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
schema.db
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
您的代码没有明显的错误,因此我检索了您的回购,安装了宝石并运行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:migrate
和rails 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 >
Note 您的测试仍然会在验证上失败,但这是一个完全独立的问题,并且您已经通过了此障碍,可以调查一个问题:)
顺便说一句,在您的研究中,您遇到了nil nil类的nomethoderror,您的代码受到保护:
user&.admin?
&
字符基本上是在说如果用户不是零,相当于:
user.admin? if user