Comments conrtoller test ActionController::UrlGenerationError - ruby-on-rails

When run rake test, I get this error: ActionController::UrlGenerationError
my routes.rb
resources :posts do
resources :comments, only: [ :create,:destroy ]
end
comments.yml
one:
body: "comment one"
user: users(:paul)
post: posts(:one)
comments_controller_test.rb
def setup
#comment = comments(:one)
end
test "should redierct create when not signed in" do
assert_no_difference "Comment.count" do
post :create, comment: #comment.attributes
end
assert_redirected_to signin_url
end
comments_controller.rb
def create
#comment = #post.comments.build(comment_params.merge(user: current_user))
#comment.save
#comments = #post.comments.all
respond_to do |format|
format.html { redirect_to #post }
format.js
end
end
Complete error message
ERROR["test_should_redierct_create_when_not_signed_in",
CommentsControllerTest, 0.444971]
test_should_redierct_create_when_not_signed_in#CommentsControllerTest
(0.44s) ActionController::UrlGenerationError:
ActionController::UrlGenerationError: No route matches
{:action=>"create", :comment=>{"id"=>"980190962", "body"=>"comment
one", "post_id"=>"849819558", "user_id"=>"293831562",
"created_at"=>"2014-11-16 10:45:03 UTC", "updated_at"=>"2014-11-16
10:45:03 UTC"}, :controller=>"comments"}
How should I modify my test code?

I think you need to explicitly tell about the parent record id (post_id) so rails can form the correct post path, try something like:
post :create, comment: #comment.attributes, post_id: #comment.post_id

Related

ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"posts"}

I'm trying to generate sitemap automatically by using a sitemap_generator gem. I tried to add show action since I started getting an error. It was originally empty..
Following is my posts controller:
class PostsController < ApplicationController
before_filter :authorize, only: [:edit, :update, :new, :create, :destroy]
before_filter :find_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.order("created_at DESC").page(params[:page]).per(9)
respond_to do |format|
format.html
format.rss { render :layout =>false }
end
end
def show
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to posts_url
else
render 'new'
end
end
def edit
end
def update
if #post.update_attributes(post_params)
redirect_to post_url(#post), notice: "#{#post.title} Updated"
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to posts_url, notice: "#{#post.title} Deleted"
end
private
def post_params
params.require(:post).permit(:title, :contents, :author_id, :approved, :summary, :preview_image_id, :category, :social_title, :blog_title)
end
def find_post
#post = Post.friendly.find(params[:id])
# If an old id or a numeric id was used to find the record, then
# the request path will not match the post_path, and we should do
# a 301 redirect that uses the current friendly id.
if params[:action] == 'show' && request.path != post_path(#post)
return redirect_to #post, :status => :moved_permanently
end
end
end
routes.rb
Rails.application.routes.draw do
root to: "home#index"
resources :posts do
resources :comments
end
end
sitemap.rb
Post.friendly.find_each do |post|
add post_url(post), :lastmod => post.created_at
end
I tried both with 'friendly' and without 'friendly'.
and When I run rake sitemap:refresh I receive the following error
ubuntu:~/environment/site (master) $ rake sitemap:refresh
In '/home/ubuntu/environment/site/public/':
Post Load (0.6ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT 1000
rake aborted!
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"posts", :format=>nil, :id=>nil, :locale=>#<Post id: 1, title: "4 Tips For Managing Your Maintenance Team", contents: "<p>Maintenance teams are a special kind of problem...", approved: nil, created_at: "2020-03-30 16:17:28", updated_at: "2020-05-04 17:07:30", url: nil, blog_title: "4 Tips For Managing Your Maintenance Team">} missing required keys: [:id]

No route matches

Background
I have created a movie review app that allows a logged in user to add and edit a movie as well as leave a review for each movie.
Problem
I am working on testing my controllers, however I keep getting:
3) Error:
ReviewsControllerTest#test_should_get_edit:
ActionController::UrlGenerationError: No route matches
{:action=>"edit_movie_review", :controller=>"reviews"}
test/controllers/reviews_controller_test.rb:34:in `block in <class:ReviewsControllerTest>'
4) Error:
ReviewsControllerTest#test_should_get_new:
ActionController::UrlGenerationError: No route matches {:action=>"new", :controller=>"reviews"}
test/controllers/reviews_controller_test.rb:17:in `block in <class:ReviewsControllerTest>'
5) Error:
ReviewsControllerTest#test_should_show_review:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"reviews", :id=>"1"}
test/controllers/reviews_controller_test.rb:29:in `block in <class:ReviewsControllerTest>'
6) Error:
ReviewsControllerTest#test_should_create_review:
ActionController::UrlGenerationError: No route matches {:action=>"create", :controller=>"reviews", :review=>{:comment=>"MyText", :rating=>"1"}}
test/controllers/reviews_controller_test.rb:23:in `block (2 levels) in <class:ReviewsControllerTest>'
test/controllers/reviews_controller_test.rb:22:in `block in <class:ReviewsControllerTest>'
Rake routes:
POST /movies/:movie_id/reviews(.:format) reviews#create
new_movie_review GET /movies/:movie_id/reviews/new(.:format) reviews#new
edit_movie_review GET /movies/:movie_id/reviews/:id/edit(.:format) reviews#edit
movie_review GET /movies/:movie_id/reviews/:id(.:format) reviews#show
PATCH /movies/:movie_id/reviews/:id(.:format) reviews#update
PUT /movies/:movie_id/reviews/:id(.:format) reviews#update
DELETE /movies/:movie_id/reviews/:id(.:format) reviews#destroy
movies GET /movies(.:format) movies#index
POST /movies(.:format) movies#create
new_movie GET /movies/new(.:format) movies#new
edit_movie GET /movies/:id/edit(.:format) movies#edit
movie GET /movies/:id(.:format) movies#show
PATCH /movies/:id(.:format) movies#update
PUT /movies/:id(.:format) movies#update
ReviewsControllerTest:
require 'test_helper'
class ReviewsControllerTest < ActionController::TestCase
setup do
#review = reviews(:one)
#user = users(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:review)
end
test "should get new" do
get :new
assert_response :success
end
test "should create review" do
assert_difference('Review.count') do
post :create, review: { comment: #review.comment, rating: #review.rating }
end
assert_redirected_to review_path(assigns(:review))
end
test "should show review" do
get :show, id: #review
assert_response :success
end
test "should get edit" do
get :edit_movie_review, #review
assert_response :success
end
test "should update review" do
put :update
assert_redirected_to review_path(assigns(:review))
end
test "should destroy review" do
assert_difference('Review.count', -1) do
delete :destroy, id: #review
end
assert_redirected_to reviews_path
end
end
ReviewsController.rb:
class ReviewsController < ApplicationController
before_action :find_movie
before_action :find_review, only: [:edit, :update, :destroy]
before_action :authenticate_user!, only: [:new, :edit]
def new
#review = Review.new
end
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
#review.movie_id = #movie.id
if #review.save #if a review is succesfully saved, redirect user to home
redirect_to movie_path(#movie)
else
render 'new'
end
end
def edit
end
def update
if #review.update(review_params)
redirect_to movie_path(#movie)
else
render 'edit'
end
end
def destroy
#review.destroy
redirect_to movie_path(#movie)
end
private
def review_params
params.require(:review).permit(:rating, :comment)
end
def find_movie
#movie = Movie.find(params[:movie_id])
end
def find_review
#review = Review.find(params[:id])
end
end
I am new to the world of programming therefore any form of advice is much appreciated.
Thanks in advance!
You can pass movie_id with your routes. Try this for your new action test and you can follow the same pattern for other actions as well.
Note: You ReviewsController does not have index and show action.
require 'test_helper'
class ReviewsControllerTest < ActionController::TestCase
setup do
#movie = movies(:one)
#review = reviews(:one)
#user = users(:one)
end
#test "should get index" do
# get :index
# assert_response :success
# assert_not_nil assigns(:review)
#end
test "should get new" do
get :new, movie_id: #movie.id
assert_response :success
end
test "should create review" do
assert_difference('Review.count') do
post :create, movie_id: #movie.id ,review: { comment: #review.comment, rating: #review.rating }
end
assert_redirected_to movie_path(assigns(:review))
end
test "should get edit" do
get :edit, movie_id: #movie.id, id: #review.id
assert_response :success
end
test "should update review" do
put :update, movie_id: #movie.id, id: #review.id, review: { comment: #review.comment, rating: #review.rating }
assert_redirected_to movie_path(assigns(:review))
end
test "should destroy review" do
assert_difference('Review.count', -1) do
delete :destroy, id: #review, movie_id: #movie.id
end
end
end

How to run minitest for controller methods?

post_controller file
class PostsController < ActionController::Base
before_action :authenticate_user!
def index
#post = current_user.posts.paginate(page: params[:page], per_page: 5)
respond_to do |format|
format.html
format.json { render json: #post }
end
end
def new
#post = Post.new
end
def create
#post = current_user.posts.build(post_param)
if #post.save
redirect_to action: 'index'
else
render 'new'
end
post_controller_test
require 'test_helper'
class PostsControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
#user = users(:Bob)
#post = Post.new
end #passed
test 'logged in should get show' do
sign_in #user
get :index
assert_response :success
end #passed
test 'not authenticated should get redirect' do
get :index
assert_response :redirect
end #passed
test 'should get index' do
get :index
assert_response :success
assert_not_nil assigns(:posts)
end #failing
test "should destroy post" do
assert_difference('Post.count', -1) do
delete :destroy, id: #post
end
assert_redirected_to posts_path
end #failing
...
devise is setup and working fine but why I am getting 302 error in last two cases. Is it because I am not passing #user parameters to it? I did but it was still throwing the same error. I also checked out my routes file which is fine because post_controller is working fine in development mode.
What I am doing wrong here?
Edit-1
I tried to create test cases for create method
def setup
#user = users(:bob)
#p = posts(:one)
#post = Post.new
end
test 'should create post' do
sign_in #user
assert_difference('Post.count') do
post :create, post: { name: #p.name, value: #p.value}
end
end
I am getting ActionController::ParameterMissing: param is missing or the value is empty: post while in my controller class I do have
params.require(:post).permit(:name, :value, :user_id)
I also have all parameters in my .yml file i.e.
one:
name: 2
value: 3
It looks like you need to sign in before trying the index action. You're also testing the wrong instance variable name. You're testing #posts, but you've defined #post in the controller. Try this test instead:
test 'should get index' do
sign_in #user
get :index
assert_response :success
assert_not_nil assigns(:post)
end

Rspec: why is my post :create throwing a :new route not found error?

In a little Rspec test like this:
describe 'POST create' do
context 'with valid attributes' do
#document = FactoryGirl.attributes_for(:document_with_publication)
it 'creates a new document' do
sign_in admin
post :create, document: #document
expect(response).to change(Document, :count).by(1)
end
end
end
I get this error:
DocumentsController user is an administrator POST create with valid attributes creates a new document
Failure/Error: post :create, document: #document
ActionController::RoutingError:
No route matches {:controller=>"documents", :action=>"new", :template=>nil}
Why do I seem to be hitting my :new action and not :create? My routes look like this:
resources :documents, except: [:new, :show]
get 'documents/:template/new', to: 'documents#new', as: :new_templated_document
Thanks. Relevant controller code is here:
def new
#document = current_user.documents.new
#document.template = Template.find(params[:template])
#template_resources = TemplateResources.new(#document, current_user)
end
def create
#document = current_user.documents.new(params[:document])
if #document.save
second_stage_processing
else
redirect_to new_templated_document_path(#document.template), flash:
{ error: 'The document you tried to create was invalid: ' \
"#{#document.errors.full_messages.map { |msg| msg }.join}" }
end
end
I think it is hitting the create action and the #document.save is failing which causes the redirect to redirect_to new_templated_document_path(#document.template) to be called. Since :template is required for that route, but is nil, the route is failing.

Rspec: No route matches {:action=>"show", :controller=>"posts", :id=>nil}

I'm trying to create a very simple blog using Rails, for my own education. It's the first Rails app I've ever created other than from working through tutorials.
So far I just have a very simple model where each post has only a string for the title and a string for the content. Everything works fine and as expected in the browser, but I can't get the tests to pass.
Here's are the failing test in my Rspec code (spec/requests/post_spec.rb):
require 'spec_helper'
describe "Posts" do
.
.
.
describe "viewing a single post" do
#post = Post.create(title: "The title", content: "The content")
before { visit post_path(#post) }
it { should have_selector('title', text: #post.title) }
it { should have_selector('h1', text: #post.title) }
it { should have_selector('div.post', text: #post.content) }
end
end
This gives me the same error message for all 3:
Failure/Error: before { visit post_path(#post) }
ActionController::RoutingError:
No route matches {:action=>"show", :controller=>"posts", :id=>nil}
So it seems to me the problem is that the line #post = Post.create(...) is creating a post without an id, or else it's not saving the post to the test database correctly. How do I fix this? And am I going about this the right way in the first place, or is there a better way I could be creating the test post/testing the page?
This is only a problem in testing. When I view a single post in the browser everything looks fine. The Posts controller is: (I have edited this since posting the original question)
class PostsController < ApplicationController
def new
#post = Post.new
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to posts_path, :notice => "Post successfully created!"
end
end
def index
end
def show
#post = Post.find(params[:id])
end
end
And here's the Post model in its entirety:
class Post < ActiveRecord::Base
attr_accessible :content, :title
validates :content, presence: true
validates :title, presence: true
end
config/routes:
Blog::Application.routes.draw do
resources :posts
root to: 'posts#index'
end
app/views/posts/show.html.erb:
<% provide(:title, #post.title) %>
<h1><%= #post.title %></h1>
<div class="post"><%= #post.content %></div>
Your instance variable needs to go into the before block. (the test is trying to goto /posts/:id/show and params[:id] in this case is nil as #post hasnt been created)
try:
before do
#post = Post.create(title: "The title", content: "The content")
visit post_path(#post)
end
Ok so it seems your new and create actions are empty?? Try
def new
#post =Post.new
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to posts_path, :notice => " Post successfully created."
end
end
and then your view for new needs to have a form_for #post
You cant create a new post without this and only when this is successful your posts will e assigned ids
Do you need to put your 'before' stuff outside the test? This works for me:
require 'spec_helper'
describe "Posts" do
before(:each) do
#post = Post.create(title: "The title", content: "The content")
end
describe "viewing a single post" do
it "should show the post details" do
get post_path(#post)
response.status.should be(200)
# do other tests here ..
end
end
end

Resources