Вопрос

I am using Devise for my user authentication and would like to destroy an associated profile along with the user.

My failing spec looks like this:

it "should destroy associated profile" do
  profile = @user.profile
  @user.destroy
  expect(profile).to be_nil
end

And

In my user model:

has_one :profile, dependent: :destroy

In my profile model:

belongs_to :user

In the console, I can reproduce the issue like this:

2.0.0p247 :001 > @user = FactoryGirl.create(:user)
   (1.5ms)  BEGIN
  User Exists (2.9ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = 'person946979@example.com' LIMIT 1
  User Exists (1.7ms)  SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('person946979@example.com') LIMIT 1
  SQL (15.7ms)  INSERT INTO "users" ("created_at", "email", "encrypted_password", "name", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["created_at", Fri, 16 Aug 2013 01:21:12 UTC +00:00], ["email", "person946979@example.com"], ["encrypted_password", "$2a$10$0704XOlw.6ZE4HEfDhaIeuwnEbbJZvZda3Jwr052aLS5z3G77Dgja"], ["name", "Example User"], ["updated_at", Fri, 16 Aug 2013 01:21:12 UTC +00:00]]
  SQL (3.8ms)  INSERT INTO "profiles" ("created_at", "updated_at", "user_id") VALUES ($1, $2, $3) RETURNING "id"  [["created_at", Fri, 16 Aug 2013 01:21:12 UTC +00:00], ["updated_at", Fri, 16 Aug 2013 01:21:12 UTC +00:00], ["user_id", 25]]
  Profile Load (3.4ms)  SELECT "profiles".* FROM "profiles" WHERE "profiles"."user_id" = $1 ORDER BY "profiles"."id" ASC LIMIT 1  [["user_id", 25]]
   (2.2ms)  COMMIT
 => #<User id: 25, email: "person946979@example.com", encrypted_password: "$2a$10$0704XOlw.6ZE4HEfDhaIeuwnEbbJZvZda3Jwr052aLS5...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2013-08-16 01:21:12", updated_at: "2013-08-16 01:21:12", name: "Example User"> 
2.0.0p247 :002 > @user.destroy
   (1.0ms)  BEGIN
  SQL (2.5ms)  DELETE FROM "profiles" WHERE "profiles"."id" = $1  [["id", 4]]
  SQL (5.4ms)  DELETE FROM "users" WHERE "users"."id" = $1  [["id", 25]]
   (2.0ms)  COMMIT
 => #<User id: 25, email: "person946979@example.com", encrypted_password: "$2a$10$0704XOlw.6ZE4HEfDhaIeuwnEbbJZvZda3Jwr052aLS5...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2013-08-16 01:21:12", updated_at: "2013-08-16 01:21:12", name: "Example User"> 

Interestingly, the user appears to actually have been deleted.

2.0.0p247 :003 > @user.reload.destroy
  User Load (2.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 25]]
ActiveRecord::RecordNotFound: Couldn't find User with id=25

What is going on here?

Это было полезно?

Решение 3

Rewriting my spec like this does what I need:

it "should destroy associated profile" do
      expect {
        @user.destroy
      }.to change(Profile, :count).by(-1)
    end

Другие советы

Your model seems fine. Try something like this:

it "should destroy associated profile" do
  profile = @user.profile
  @user.destroy
  expect(Profile.find(profile.id)).to be_nil
end

Like Heungju said, while the database row that corresponds to profile is being destroyed, the variable itself isn't.

How about this?

it "should destroy associated profile" do
  profile = @user.profile
  @user.destroy
  expect(@user.profile).to be_nil
end

After @user.destroy, the 'profile', variable that expected to be nil, was not changed. I think...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top