Добавьте тесты для зависимого :destroy в модели отношений (Глава 11, Упражнение 1 Учебник по Rails, 2-е изд.)

Почти уверен, что эти тесты работают правильно. Принудил их к сбою, удалив параметры depend::destroy в has_many:relationships и has_many:reverse_relationships в user.rb.

Хотел поделиться тем, что я сделал, на случай, если кто-то еще работает с Майкла Хартла. Учебное пособие по Rails, 2-е издание, глава 11, упражнения.

В связи с этим упражнением возникло несколько вопросов (см. внизу этого поста). Если бы кто-нибудь мог помочь, это было бы здорово.

Глава 11, упражнение 1:

Добавьте тесты для зависимого :destroy в модели отношений (листинги 11.4 и листинги 11.16), следуя примеру из листинга 10.15.

Вот мой тест: spec/models/user_spec.rb

require 'spec_helper'

describe User do

  before do
  @user = User.new(name: "Example User", email: "[email protected]", 
                   password: "foobar", password_confirmation: "foobar")
  end

  subject { @user }

  [...code omitted...]

  describe "relationship associations" do
    let(:other_user) { FactoryGirl.create(:user) }
    before do
      @user.save
      @user.follow!(other_user)
      other_user.follow!(@user)
    end

    it "should destroy associated relationships" do
      relationships = @user.relationships
      @user.destroy
      relationships.should be_empty
    end

    it "should destroy associated reverse relationships" do
      reverse_relationships = @user.reverse_relationships
      @user.destroy
      reverse_relationships.should be_empty
    end
  end

По этому упражнению возникло несколько вопросов:

Вопрос 1:

Моими первоначальными тестами были отношения.

Но понял, что массив все еще возвращается, несмотря на отсутствие пользователя. Итак, когда пользователь не существует и вызывается метод ассоциации, результат все равно остается массивом? Всегда ли это так?

Вопрос 2:

Я хотел поиграть с удалением отношений и reverse_relationships для пользователя в консоли rails.

я пробовал это

> user = User.first
> user.relationships
 # returns a bunch of relationships
> user.relationships.destroy
=> []
> user.relationships
 # returns same bunch of relationships

Как мне на самом деле разрушить отношения навсегда? Кажется, это полезно знать при изучении в консоли.

Спасибо! Я все еще новичок в Rails


person Brett Sanders    schedule 20.04.2012    source источник


Ответы (6)


Я тоже новичок в ruby/rails.

Вопрос 1. На rubyonrails.org выполнен поиск has_many, и он говорит:

Возвращает массив всех связанных объектов. Если ничего не найдено, возвращается пустой массив.

Кстати, вы можете проверить как nil, так и empty:

relationships.present?.should be_false

Вопрос 2: user.relationships.destroy требует :id

user.relationships.destroy '1'
person EricM    schedule 24.04.2012

может быть вам нужно смт, как это

it { should have_many(:relationships).dependent(:destroy) }
person xab3r    schedule 29.08.2014

Спасибо за публикацию вашего кода с вашим вопросом. Я только хотел опубликовать это как комментарий, а не как ответ, но, похоже, пока не могу. В любом случае, я просто хотел добавить к вашим тестам небольшого потенциального кандидата, но с точки зрения other_user. Тест похож на тесты Follow/Unfollow, так что, надеюсь, он не будет слишком избыточным, но он проверяет relationships напрямую, а не followed_users и followers, которые проходят через них.

describe "relationship associations" do
  ...
  context "when a follower/followed user is destroyed" do
    subject { other_user }

    before { user.destroy }

    its(:relationships) { should_not include(user) }
    its(:reverse_relationships) { should_not include(user) }
  end
end
person Paul Fioravanti    schedule 10.06.2012

Учебное пособие по Ruby on Rails, 2-е издание.

Упражнение 11.5.1 Добавьте тесты для разрушения отношений, связанных с данным пользователем.

Этот код работает для меня. Я попытался следовать примеру Listing 10.15.

spec/models/user_spec.rb

require 'spec_helper'

describe User do

  before do 
    @user = User.new(name: "Example User", email: "[email protected]", password: "foobar", password_confirmation: "foobar")
  end

  subject { @user }
  .
  .
  .
  .
  describe "user relationships associations" do
    let (:other_user) { FactoryGirl.create(:user) }
    let (:another_user) { FactoryGirl.create(:user) }

    before do
      @user.save
      @user.follow!(other_user)
      @user.follow!(another_user)
      other_user.follow!(@user)
      other_user.follow!(another_user)
      another_user.follow!(@user)
      another_user.follow!(other_user)
    end

    its(:followed_users) { should include(other_user) }
    its(:followers) { should include(another_user) }

    it "should destroy associated followers" do
      followers = @user.followers
      @user.destroy
      followers.each do |follower|
        follower.followed_users.should_not include(@user)
      end
    end

    it "should destroy associated followed users" do
      followed_users = @user.followed_users
      @user.destroy
      followed_users.each do |followed_user|
        followed_user.followers.should_not include(@user)
      end
    end
  end
end
person maria    schedule 25.08.2012

Re: Пол, массив отношений не состоит из пользователей, поэтому его include() всегда должен быть ложным, поэтому тест всегда зеленый. Re: Мария, похоже, что методы Follow_users и Followers не вернут пользователя, которого не существует, даже если отношение, ссылающееся на него или ее, сохраняется. Так что этот тест тоже никогда не бывает красным.

другое решение:

  describe "relationships" do
    let(:other_user) { FactoryGirl.create(:user) }
    before do
      @user.save
      @user.follow!(other_user)
    end

    let(:relationship) { @user.relationships.last }

    describe "should be destroyed when the followed user is destroyed" do
      before { other_user.destroy }
      its(:relationships) { should_not include(relationship) }
    end

    describe "should be destroyed when the following user is destroyed" do
      subject { other_user }
      before { @user.destroy }
      its(:reverse_relationships) { should_not include(relationship) }
    end
  end
person dstandish    schedule 12.10.2013

Приведенные выше ответы работают, но я думаю, что поделюсь своим, он короче .. : D

describe "following" do

  let(:other_user) { FactoryGirl.create(:user) }
  before do
    @user.save
    @user.follow!(other_user)
    other_user.follow!(@user)
  end

   it { should be_following(other_user) }
   its(:followed_users) { should include(other_user) }

   it "should destroy associated followed_users and followers" do
     @user.destroy
     @user.relationships.present?.should be_false
     @user.reverse_relationships.present?.should be_false

     expect(other_user.followers).not_to include(@user)
     expect(other_user.followed_users).not_to include(@user)
   end
   .
   .
   .
   .
 end
end

P.S. можно опустить:

@user.relationships.present?.should be_false
@user.reverse_relationships.present?.should be_false

но я добавляю это туда для тех, кто хочет убедиться, что все связанные действия по уничтожению работают.

person Steve007    schedule 18.11.2013