Im in the last chapter of Ruby on Rails tutorial by M.Hartl and I'm facing the problem with actions 'create' and 'destroy'
I already checked title of my all files. I receive errors during tests:
ERROR["test_should_unfollow_a_user_with_Ajax", FollowingTest, 2015-12-03 23:12:38 +0000] test_should_unfollow_a_user_with_Ajax#FollowingTest (1449184358.75s) AbstractController::ActionNotFound: AbstractController::ActionNotFound: The action 'destroy' could not be found for RelationshipsController
test/integration/following_test.rb:53:in `block (2 levels) in <class:FollowingTest>'
test/integration/following_test.rb:52:in `block in <class:FollowingTest>'
test/integration/following_test.rb:53:in `block (2 levels) in <class:FollowingTest>'
test/integration/following_test.rb:52:in `block in <class:FollowingTest>'
The same error is for create action.
relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :logged_in_user
def create
#user = User.find(params[:followed_id])
current_user.follow(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users do
member do
get :following, :followers
end
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :relationships, only: [:create, :destroy]
end
following_test.rb
require 'test_helper'
class FollowingTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
#other = users(:archer)
log_in_as(#user)
end
test "following page" do
get following_user_path(#user)
assert_not #user.following.empty?
assert_match #user.following.count.to_s, response.body
#user.following.each do |user|
assert_select "a[href=?]", user_path(user)
end
end
test "followers page" do
get followers_user_path(#user)
assert_not #user.followers.empty?
assert_match #user.followers.count.to_s, response.body
#user.followers.each do |user|
assert_select "a[href=?]", user_path(user)
end
end
test "should follow a user the standard way" do
assert_difference '#user.following.count', 1 do
post relationships_path, followed_id: #other.id
end
end
test "should follow a user with Ajax" do
assert_difference '#user.following.count', 1 do
xhr :post, relationships_path, followed_id: #other.id
end
end
test "should unfollow a user the standard way" do
#user.follow(#other)
relationship = #user.active_relationships.find_by(followed_id: #other.id)
assert_difference '#user.following.count', -1 do
delete relationship_path(relationship)
end
end
test "should unfollow a user with Ajax" do
#user.follow(#other)
relationship = #user.active_relationships.find_by(followed_id: #other.id)
assert_difference '#user.following.count', -1 do
xhr :delete, relationship_path(relationship)
end
end
end
Does anyone have any idea what's the problem? I checked other questions of this error and none of them are applicable to my application.
Many thanks in advance for help!
Related
Why do I get the following, "undefined method `micropost_path'" in StaticPagesController , error, even though I copied Hartl's code verbatim?
Below is some of the code.
routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :edit]
end
StaticPages Controller
class StaticPagesController < ApplicationController
def home
if logged_in?
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
def help
end
def about
end
def contact
end
end
MicropostsController
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#micropost.destroy
flash[:success] = "Micropost deleted"
redirect_to request.referrer || root_url
end
private
def micropost_params
params.require(:micropost).permit(:content)
end
def correct_user
#micropost = current_user.microposts.find_by(id: params[:id])
redirect_to root_url if #micropost.nil?
end
end
Two of the answers, on this website, to this issue were solved for other reasons.
For example writing
micropost
instead of
microposts
I don't have these grammatical errors here if I am not mistaken.. Any idea what other problem could be causing this?
P.S. Using cloud9 IDE while following tutorial.
In routes.rb I had the following resources for microposts
resources :microposts, only: [:create, :edit]
Instead,it is supposed to be
resources :microposts, only: [:create, :destroy]
The
:destroy
was missing.
Found this out after running 'rake routes'..
got this route
edit_micropost GET /microposts/:id/edit(.:format) microposts#edit
instead of
micropost DELETE /microposts/:id(.:format) microposts#destroy
This shows the routes with their corresponding actions that should be in the controller.
I have been trying to get my controller test pass...
My routes.rb
namespace :school do
resource :account, :except => [:new, :create, :destroy], :controller => 'account'
resources :classes, :path => "" do
resources :discussions do
resources :comments
end
resources :materials
end
end
MY DiscussionController specs:
describe "POST 'create'" do
before(:each) do
#user = FactoryGirl.create(:coordinator_user)
login_user(#user)
#klass = FactoryGirl.build(:klass)
#klass.creator = #user
#klass.save
#parameters = FactoryGirl.attributes_for(:discussion, :klass_id => #klass, :user_id => #user)
end
context "with valid parameters" do
it "creates a new job" do
expect { post :create, :class_id => #klass.id, :discussion => #parameters }.to change(Discussion, :count).by(1)
end
it "should create a new discussion" do
post :create, :class_id => #klass.id
response.should be_redirect
response.should redirect_to(school_account_path(assigns(:discussion).id))
assigns(:discussion).should_not be_nil
assigns(:discussion).should_not be_new_record
end
end
I get errors: 1) NoMethodError: undefined method empty?' for nil:NilClass # ./lib/slug.rb:3:inslug'
Cannot understand what is nil here.
my routes.rb
namespace :magazine do
resources :pages do
resources :articles do
resources :comments
end
end
end
While writing controller specs for Comments:
describe "GET 'index'" do
before(:each) do
#user = FactoryGirl.create(:user)
#page = FactoryGirl.build(:page)
#page.creator = #user
#page.save
#article = FactoryGirl.create(:article)
#comment_attributes = FactoryGirl.attributes_for(:comment, :article_id => #article )
end
it "populates an array of materials" do
get :index, ??
#response.should be_success
assigns(:comments)
end
it "renders the :index view" do
get :index, ??
response.should render_template("index")
end
end
Any idea how to give the page and article reference to get :index ??
if I give : get :index, :article_id => #article.id
Error I get is below:
Failure/Error: get :index, :article_id => #article.id
ActionController::RoutingError:
No route matches {:article_id =>"3", :controller=>"magazine/comments"}
Your route requires at least two IDs: the comment's parent article, and the article's parent page.
namespace :magazine do
resources :pages do
resources :articles do
resources :comments
end
end
end
# => /magazine/pages/:page_id/articles/:article_id/comments
All parent IDs must be provided for this route to work:
it "renders the :index view" do
get :index, {:page_id => #page.id, :article_id => #article.id}
# [UPDATE] As of Rails 5, this becomes:
# get :index, params: {:page_id => #page.id, :article_id => #article.id}
response.should render_template("index")
end
With Rails 5 the params API changed:
get :index, params: { page_id: #page.id, article_id: #article.id }
https://relishapp.com/rspec/rspec-rails/v/3-7/docs/request-specs/request-spec#specify-managing-a-widget-with-rails-integration-methods
Im following the rails tutorial and I've had some problems with the test but one particular error is this:
1) UsersController following pages when not signed in should protect 'following'
Failure/Error: get :following, :id => 1
ActionController::RoutingError:
No route matches {:id=>1, :controller=>"users", :action=>"following"}
# ./spec/controllers/users_controller_spec.rb:10:in `block (4 levels) in <top (required)>'
I don't understand why It's happening if I have this on my routes.rb
resources :users do
member do
get :following, :followers
end
end
and my controller is this:
class UsersController < ApplicationController
before_filter :authenticate, :except => [:show, :new, :create]
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(:page => params[:page])
render 'show_follow'
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following.paginate(:page => params[:page])
render 'show_follow'
end
end
and here is my rspec:
it "should protect 'following'" do
get :following, :id => 1
response.should redirecto_to (new_selector_session_en_path)
end
also my routes:
following_user_en GET /users/:id/following(.:format) {:action=>"following", :controller=>"users"}
following_user_es GET /es/usuarios/:id/following(.:format) {:action=>"following", :controller=>"users"}
followers_user_en GET /users/:id/followers(.:format) {:action=>"followers", :controller=>"users"}
followers_user_es GET /es/usuarios/:id/followers(.:format) {:action=>"followers", :controller=>"users"}
I've been receiving the following error in my RSpec when trying to get my upvote method to pass:
Failures:
1) VotesController#up_vote adds an up-vote to the post
Failure/Error: post( :up_vote, post_id: #post.id )
ActionController::UrlGenerationError:
No route matches {:action=>"up_vote", :controller=>"votes", :post_id=>"1"}
Now I can upvote and downvote when I'm on the server, it's just my test that won't work.
Here's my code:
votes_controller_spec.rb
require 'rails_helper'
describe VotesController do
include TestFactories
include Devise::TestHelpers
describe '#up_vote' do
it "adds an up-vote to the post" do
request.env["HTTP_REFERER"] = '/'
#user = authenticated_user
#post = associated_post
sign_in #user
expect {
post(:up_vote, post_id: #post.id)
}.to change { #post.up_votes }.by 1
end
end
end
votes_controller.rb
class VotesController < ApplicationController
before_action :load_post_and_vote
def up_vote
update_vote!(1)
redirect_to :back
end
def down_vote
update_vote!(-1)
redirect_to :back
end
def update_vote!(new_value)
if #vote
authorize #vote, :update?
#vote.update_attribute(:value, new_value)
else
#vote = current_user.votes.build(value: new_value, post: #post)
authorize #vote, :create?
#vote.save
end
end
private
def load_post_and_vote
#post = Post.find(params[:post_id])
#vote = #post.votes.where(user_id: current_user.id).first
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:update]
resources :questions
resources :advertisements
resources :topics do
resources :posts, except: [:index] do
resources :summaries, only: [:create, :new, :show]
resources :comments, only: [:create, :destroy]
post '/up-vote', to: 'votes#up_vote', as: :up_vote
post '/down-vote', to: 'votes#down_vote', as: :down_vote
end
end
get 'about' => 'welcome#about'
get 'contact' => 'welcome#contact'
root to: 'welcome#index'
end
Module providing methods within specs:
module TestFactories
def associated_post(options={})
post_options = {
title: 'Post title',
body: 'Post bodies must be pretty long.',
topic: Topic.create(name: 'Topic name'),
user: authenticated_user
}.merge(options)
Post.create(post_options)
end
def authenticated_user(options={})
user_options = {email: "email#{rand}#fake.com", password: 'password'}.merge(options)
user = User.new(user_options)
user.skip_confirmation!
user.save
user
end
end
Relevant Rake Routes
topic_post_up_vote POST /topics/:topic_id/posts/:post_id/up-vote(.:format) votes#up_vote
topic_post_down_vote POST /topics/:topic_id/posts/:post_id/down-vote(.:format) votes#down_vote
Any ideas why I'm getting this URL generation error?
I think you just need to pass the topic_id to the post method like this: post( :up_vote, post_id: #post.id, topic_id: #post.topic.id )
I ended up switching my routes.rb file to the below and got the above vote_controller_spec.rb working.
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:update]
resources :questions
resources :advertisements
resources :topics do
resources :posts, except: [:index]
end
resources :posts, only: [] do
resources :summaries, only: [:create, :new, :show]
resources :comments, only: [:create, :destroy]
post '/up-vote', to: 'votes#up_vote', as: :up_vote
post '/down-vote', to: 'votes#down_vote', as: :down_vote
end
get 'about' => 'welcome#about'
get 'contact' => 'welcome#contact'
root to: 'welcome#index'
end