我无法使规范传递给关系控制器。我必须在控制器或controller_spec中更改有关我的对象的内容。 随意对我的控制器提出任何疑问......谢谢
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
答案 0 :(得分:1)
问题的根源在于,Relationship.find(params[:id]).followed
因某种原因返回nil,导致后续行current_user.unfollow(user)
向您提供您所看到的错误。
您确定create(:relationship)
工厂正在followed
正确设置Relationship
个关联吗?
此外,查看您的控制器规范,您将两次定义let!(:relationship) { create(:relationship) }
很奇怪。
为什么不在规范的开头声明一个let!(:relationship) { create(:relationship) }
(!
)?
最后,在find
方法中使用find_by
代替unfollow
可能更合适,以防止在{{{}}上调用destroy
1}}不存在。