2016-05-08 3 views
1

Я не могу заставить спецификацию перейти в контроллер отношений. Я должен что-то изменить о своем объекте в контроллере или контроллере_спец. Не стесняйтесь задавать любые сомнения по поводу моего контроллера ... спасибоОшибка RSpec (неопределенный метод `id 'для nil: NilClass) с has_many через модель

user.rb

class User < ActiveRecord::Base 

    # Associations 
    has_many :active_relationships, class_name: "Relationship", 
            foreign_key: "follower_id", 
            dependent: :destroy 
    has_many :passive_relationships, class_name: "Relationship", 
            foreign_key: "followed_id", 
            dependent: :destroy 
    has_many :following, through: :active_relationships, source: :followed 
    has_many :followers, through: :passive_relationships, source: :follower 

    # Follows a user. 
    def follow(other_user) 
    active_relationships.create(followed_id: other_user.id) 
    end 

    # Unfollows a user. 
    def unfollow(other_user) 
    active_relationships.find_by(followed_id: other_user.id).destroy 
    end 

    # Returns true if the current user is following the other user. 
    def following?(other_user) 
    following.include?(other_user) 
    end 
end 

user_spec:

require 'rails_helper' 

RSpec.describe User, :type => :model do 
    let(:user) { build(:user) } 

    describe 'Validations' do 
    it 'has a valid factory' do 
     expect(user).to be_valid 
    end 

    let(:user) { create(:user) } 
    let(:other_user) { create(:user) } 

    describe '#following?' do 
    it "expect relationship between two users to be empty" do 
     expect(user.active_relationships).to be_empty 
    end 
    end 

    describe '#follow' do 
    it "creates the active relationship between two users" do 
     user.follow(other_user) 
     expect(user.active_relationships.first.followed_id).to eq(other_user.id) 
    end 

    it "creates the passive relationship between two users" do 
     user.follow(other_user) 
     expect(other_user.passive_relationships.first.follower_id).to eq(user.id) 
    end 
    end 

    describe '#unfollow' do 
    it "destroys the active relationship between two users" do 
     user.follow(other_user) 
     expect{ 
     user.unfollow(other_user) 
     }.to change(Relationship, :count).by(-1) 
    end 
    end 
end 

relationship.rb

class Relationship < ActiveRecord::Base 
    #Associations 
    belongs_to :follower, class_name: "User" 
    belongs_to :followed, class_name: "User" 

#Validations 
    validates :follower_id, presence: true 
    validates :followed_id, presence: true 
end 

relationships_controller.rb

class RelationshipsController < InheritedResources::Base 

    def create 
    user = User.find(params[:followed_id]) 
    current_user.follow(user) 
    redirect_to user 
    end 

    def destroy 
    user = Relationship.find(params[:id]).followed 
    current_user.unfollow(user) 
    redirect_to user 
    end 
end 

relationships_controller_spec.rb

require 'rails_helper' 

describe RelationshipsController do 
    let(:relationship) { create(:relationship) } 
    let(:user) { create(:user) } 

    before do 
    sign_in :user, create(:user) 
    end 

    describe '#create' do 
    let!(:followed) { create(:user) } 
    it "should require logged-in user to create relationship" do 
     expect{ 
     post :create, followed_id: followed.id 
     }.to change(Relationship, :count).by(1) 
     redirect_to root_path 
    end 
    end 

    describe '#destroy' do 
    let!(:relationship) { create(:relationship) } 

    it "should require logged-in user to destroy relationship" do 
     expect { 
     delete :destroy, id: relationship.id 
     }.to change(Relationship, :count).by(-1) 
     redirect_to root_path 
    end 
    end 
end 

Отношения Фабрика:

FactoryGirl.define do 
    factory :relationship do 
    follower_id 1 
    followed_id 1 
    end 
end 

Неудачи:

1) RelationshipsController#destroy should require logged-in user to destroy relationship 
    Failure/Error: active_relationships.find_by(followed_id: other_user.id).destroy 

    NoMethodError: 
     undefined method `id' for nil:NilClass 

Для find вместо find_by:

2) User#unfollow destroys the active relationship between two users 
    Failure/Error: active_relationships.find(followed_id: other_user.id).destroy 

    ActiveRecord::StatementInvalid: 
     PG::UndefinedTable: ERROR: missing FROM-clause entry for table "id" 
     LINE 1: ...ips" WHERE "relationships"."follower_id" = $1 AND "id"."foll... 
                    ^
     : SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = $1 AND "id"."followed_id" = 36 LIMIT 1 

ответ

1

Источником проблемы является то, что по какой-то причине Relationship.find(params[:id]).followed возвращает нуль, вызывая последующую строку, current_user.unfollow(user), чтобы дать вам ошибку, которую вы видите.

Вы уверены, что ваш завод create(:relationship) правильно настроил followed в Relationship?

Также, глядя на ваш контроллер спецификации, странно, что вы определяете let!(:relationship) { create(:relationship) } дважды.

Почему бы не объявить один let!(:relationship) { create(:relationship) }!) в начале ваших спецификаций?

Наконец, это может быть более целесообразно использовать find вместо find_by в методе unfollow для предотвращения вызова destroy на ноль, в том случае, если find_by(followed_id: other_user.id) не существует.

+0

почта была обновлена ​​с завода и relationships.rb. Отвечая на ваш первый вопрос: я думаю, что это так, как вы можете видеть в обновленном сообщении. Второе: Спасибо за предложение, я исправил это :). В-третьих, использование 'find' вместо' find_by' rspec дает ошибку, как вы можете видеть выше. – Jony

 Смежные вопросы

  • Нет связанных вопросов^_^