当我运行以下测试时:
describe "Ghost pages" do
subject { page }
let(:user) { FactoryGirl.create(:user) }
before do
user.save
end
describe "for signed-in user" do
before do
sign_in user
end
describe "trying to view his own ghost" do
before do
visit ghost_path(user.ghost)
end
it { should have_title('Ghost') }
end
end
end
我收到以下错误,我无法确定原因:
失败/错误:访问ghost_path(user.ghost)
的ActiveRecord :: RecordNotFound:
找不到ID = 429的Ghost
./ app / controllers / ghosts_controller.rb:48:在`correct_ghost'
每个用户都有一个鬼。当用户注册并创建时,会自动创建重影(self.create_ghost)。也许鬼魂不能以某种方式正确保存?
相关的代码位是:
class User < ActiveRecord::Base
has_one :ghost, dependent: :destroy
before_create :create_remember_token
before_save do
email.downcase!
self.create_ghost
end
validates :name, presence: true,
length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }
end
class Ghost < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
end
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :show, :edit, :update, :destroy]
before_action :non_signed_in_user, only: [:new, :create]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
@users = User.paginate(page: params[:page])
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
sign_in @user
flash[:success] = "Welcome!"
redirect_to @user
else
render 'new'
end
end
end
class GhostsController < ApplicationController
before_action :signed_in_user
before_action :correct_ghost, only: [:show]
before_action :correct_destroyer, only: [:destroy]
before_action :go_away, only: [:index, :edit, :update]
def index
end
def edit
end
def update
end
def show
@ghost = Ghost.find(params[:id])
end
def new
@ghost = Ghost.new
end
def create
@ghost = current_user.build_ghost(ghost_params)
if @ghost.save
flash[:success] = "Ghost successfully created"
else
flash[:error] = "Ghost creation failed"
end
end
def destroy
@ghost = Ghost.find(params[:id])
@ghost.destroy
flash[:success] = "Ghost deleted, master."
redirect_to current_user
end
private
def ghost_params
params.require(:ghost).permit()
end
def correct_ghost
@ghost = Ghost.find(params[:id])
redirect_to(root_url) unless (current_user.id == @ghost.user_id)
end
def correct_destroyer
redirect_to(root_url) unless current_user.admin?
end
def go_away
redirect_to(root_url)
end
end
答案 0 :(得分:3)
let(:user) { FactoryGirl.create(:user) }
before do
user.save
end
执行before
块时user
返回新创建的用户,然后在其上调用save
。因此before_save
回调将运行两次。当我运行你的代码部分时,我看到:
Failed to remove the existing associated ghost. The record failed to save after its foreign key was set to nil.
您的结果可能会有所不同。无论如何,你不想创造两个幽灵。
您可以更改回调以避免在存在时创建重影:
before_save do
create_ghost unless ghost
end
但最好使用before_create
,因为你只需要创建一次幽灵。
before_create do
create_ghost
end
答案 1 :(得分:1)
您在保存Ghost
之前创建User
,因此用户没有ID,并且ghost验证失败。将其移至after_save
回调:
after_save do
self.create_ghost
end
从语义上讲,根据你的代码dependent: :destroy
在没有用户对象的情况下不能存在的ghost对象也会在其用户之后创建。