Reputation: 157
Need some help to make rspec test to pass, my goal is to delete a relationship that has been created with the method has_many throw. I followed this MHartl's tutorial.
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
routes.rb :
Rails.application.routes.draw do
devise_for :users, controllers: { sessions: "users/sessions" }
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
mount Peek::Railtie => '/peek'
resources :users do
member do
get :following, :followers
end
end
resources :relationships, only: [:create, :destroy]
root to: "records#index"
end
user.rb:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:validatable, :confirmable, :timeoutable
# 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
Factory:
FactoryGirl.define do
factory :relationship do
follower_id 1
followed_id 1
end
end
Failures:
1) Relationships GET /relationships works! (now write some real specs)
Failure/Error: get relationships_path
ActionController::RoutingError:
No route matches [GET] "/relationships"
2) 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
Upvotes: 0
Views: 323
Reputation: 18454
Your route for destroy is /relationships/:id
and controller destroys the relation, but instead of passing relation's :id
you're passing :followed_id
, so indeed there's no such route.
So you can either modify your routes and controller or to make current code work change to:
delete :destroy, id: relationship.id
(you may then get an error about relationship not having a user, depending on factory)
Upvotes: 1