I am running a test that is failing with the following message:
1) User pages profile page
Failure/Error: before { visit user_path(user) }
ActionView::Template::Error:
undefined local variable or method `new_key_path' for #<#<Class:0x007fa775c4bc50>:0x007fa775c48910>
# ./app/views/users/show.html.erb:21:in `_app_views_users_show_html_erb__4517315841728073114_70178605538620'
# ./spec/requests/user_pages_spec.rb:58:in `block (3 levels) in <top (required)>'
However, when I look at the page and follow the link manually, it works as it should. This is the test's code:
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
# let!(:key1) { FactoryGirl.create(:key) }
let!(:key1) { user.keys.build(name: "test", description: "test description", is_public: false) }
before { visit user_path(user) }
it { should have_content(user.name) }
it { should have_title(user.name) }
describe "keys" do
it { should have_content(key1.name) }
it { should have_content(key1.description) }
end
end
The 'show' page in question is:
<div class="row">
<div class="span12">
<% if #user.keys.any? %>
<h3>My Keys (<%= #user.keys.count %>)</h3>
<ol class="microposts">
<%= render #keys %>
</ol>
<%= will_paginate #keys %>
<% end %>
<%= link_to "New Key", new_key_path,
class: "btn btn-large" %>
Any idea what is causing the test to fail?
On a somewhat unrelated note, you might have noticed that I am not using a factory for :key1. This is because I kept getting this error when using it:
1) User pages profile page
Failure/Error: let!(:key1) { FactoryGirl.create(:key) }
ArgumentError:
Factory not registered: key
# ./spec/requests/user_pages_spec.rb:55:in `block (3 levels) in <top (required)>'
Despite my factories.rb file having :key in it:
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:email) { |n| "person_#{n}#example.com"}
password "foobar"
password_confirmation "foobar"
factory :admin do
admin true
end
end
factory :key do
name "Test Key"
description "This is a test key"
is_public false
user
end
end
Any help would be much appreciated. Thanks.
EDIT: Added routes
SampleApp::Application.routes.draw do
get "keys/new"
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :keys, only: [:index, :new, :destroy, :create]
root to: 'static_pages#home'
match '/signup', to: 'users#new', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
end
Result of rake routes:
Prefix Verb URI Pattern Controller#Action
keys_new GET /keys/new(.:format) keys#new
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
keys GET /keys(.:format) keys#index
POST /keys(.:format) keys#create
new_key GET /keys/new(.:format) keys#new
key DELETE /keys/:id(.:format) keys#destroy
root GET / static_pages#home
signup GET /signup(.:format) users#new
signin GET /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
help GET /help(.:format) static_pages#help
about GET /about(.:format) static_pages#about
contact GET /contact(.:format) static_pages#contact
Given that it worked after restarting spork, you've likely encountered one of the cases where spork does not pick up changes you've made. See Spork/Autotest not picking up changes automatically for discussion and the highest voted answer for workarounds.
You're probably able to see the page when you manually go to it in your browser, but upon visiting "New Key", you should have problems seeing the "New Key" page, because new_key_path doesn't exist.
If key is meant to be a child of user, then it should be new_user_key_path instead, assuming your routes are properly set up:
resources :users do
resources :keys
...
end
Try using new_user_key_path instead of:
<%= link_to "New Key", new_key_path,
class: "btn btn-large" %>
In your show.
Otherwise, if key is not meant to be a child of user,
Your factory for key1 isn't registering because you need to define a separate FactoryGirl factory for it.
FactoryGirl.define do
factory :key do
...
end
end
It is currently being treated as a child of user. If you properly indent your code, you'll realize you left it out:
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:email) { |n| "person_#{n}#example.com"}
password "foobar"
password_confirmation "foobar"
factory :admin do
admin true
end
end
# Missing end
# Missing FactoryGirl.define do
factory :key do
name "Test Key"
description "This is a test key"
is_public false
user
end
end
Related
I have started working on Chapter 8 of the famous Rails tutorial. I think I followed the instructions closely and defined the following routes:
SampleApp::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
root 'static_pages#home'
match '/signup', to: 'users#new', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
The session controller (/controllers/sessions_controller.rb) is defined as follows:
class SessionsController < ApplicationController
def new
end
def create
end
def destroy
end
end
In spec/requests/authentication_pages_spec.rb I have created the following test:
require 'spec_helper'
describe "Authentication" do
subject {page}
describe "signin page" do
before { visit signin_path}
it { should have_content('Sign in')}
it { should have_title('Sign in')}
end
end
The test causes the following errors:
Failures:
1) Authentication signin page
Failure/Error: before { visit signin_path}
NameError:
undefined local variable or method `signin_path' for #
<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x007f98dec05fe8>
# ./spec/requests/authentication_pages_spec.rb:7:in `block (3 levels) in <top (required)>'
2) Authentication signin page
Failure/Error: before { visit signin_path}
NameError:
undefined local variable or method `signin_path' for #
<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x007f98dec5cf50>
# ./spec/requests/authentication_pages_spec.rb:7:in `block (3 levels) in <top (required)>'
It seems the signin_path named route is not recognised even though it is defined in routes.rb. I replaced that named route with one of the others (signup_path) and the problem disappeared. So, it is something about this particular named route. Can you tell what the problem is?
rake routes produces the following output:
sb7904313:sample_app nnikolo$ rake routes
Prefix Verb URI Pattern Controller#Action
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
root GET / static_pages#home
signup GET /signup(.:format) users#new
signin GET /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
help GET /help(.:format) static_pages#help
about GET /about(.:format) static_pages#about
contact GET /contact(.:format) static_pages#contact
I also re-started the server and it did not solve the problem (I made a post to the contrary but I was wrong).
Try this instead. You can access your route names by the command rake routes. Since it's coming from your sessions controller, by default the route is probably something like new_session_path. To change it, you need to specify what you what to change it to in your routes with as: new_name
match '/signin', to: 'sessions#new', via: 'get', as: 'signin'
Try:--
get "signin" => "sessions#new", :as => "signin"
resources :sessions
Use the route as new_session_path or signin_path
See this thread: undefined method `visit' when using RSpec and Capybara in rails
You possibly did not have the line config.include Capybara:DSL in your spec_helper.rb and something about putting the tests inside rspec/features/ due to the latest changes in Capybara.
I was wrong about the re-start solving the problem so retract this post.
==EDIT I found the culprit for this erratic behaviour of rspec: rails does not seem to empty the cache between tests (which is, in my opinion, a scary bug). By default it fails to re-read the files and thus may ignore changes that have occurred. I put more details here: Rails tutorial: Rails tutorial: undefined method
I am trying to work through the Rails tutorial at railstutorial.org and am stuck at this problem. My user_path in the test is supposed to go to the individual user's profile page, but is instead going to users/index (which I haven't created yet, on purpose).
/* My test code */
describe "profile page" do
#let(user) { FactoryGirl.create(:user) }
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
before { visit user_path(#user) }
it { should have_content(user.name) }
it { shoult have_title(user.name) }
end
/* Failures: */
1) UserPages profile page
←[31mFailure/Error:←[0m ←[31mbefore { visit user_path(#user) }←[0m
←[31mActionView::MissingTemplate←[0m:
←[31mMissing template users/index, application/index with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffe
}. Searched in:←[0m
←[31m * "C:/Users/rajeshch/Documents/Projects/sample_app/app/views"←[0m
[36m # C:in `find_template'←[0m
[36m # ./spec/requests/user_pages_spec.rb:19:in `block (3 levels) in <top (required)>'←[0m
The routes file shows that user_path should give me users/{id} or so
> rake routes
Prefix Verb URI Pattern Controller#Action
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show <<<------
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
root GET / static_pages#home
signup GET /signup(.:format) users#new
help GET /help(.:format) static_pages#help
about GET /about(.:format) static_pages#about
contact GET /contact(.:format) static_pages#contact
/* users_controller.rb*/
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
end
end
/* config/routes.rb */
SampleApp::Application.routes.draw do
resources :users
root 'static_pages#home'
match '/signup', to: 'users#new', via: 'get'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
end
You should save the User first with #user.save! before calling visit user_path(#user)
Because until you save the user it wont persist in the database and will not have any id.
describe "profile page" do
#let(user) { FactoryGirl.create(:user) }
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
# Add this to your code ..
#user.save!
before { visit user_path(#user) }
it { should have_content(user.name) }
it { shoult have_title(user.name) }
end
Have you checked if #user has a value?
user_path(#user) will go to /users/<#user.id> but if #user is nil, it will try to go /users/. Given you haven't created the index method and views yet, that will probably be why it fails.
Thanks for the test code. Firstly your user is not in the database - change the .new to .create or add a #user.save. Secondly your params[:id] is not populated in the test code so the find will fail (add controller.params[:id] = #user.id to your test). (Thirdly you have a typo shoult instead of should in the last test.)
It doesn't seem like you included your test code, which would be immensely helpful in figuring out this problem. Most likely, you have #user set as nil in the test, fixing that will solve the problem.
In rails how do I do a link_to a user show page of the current user. Basically i want a link that go to a account page.
I tried it but i get this.
Routing Error No route matches {:action=>"show", :controller=>"users"}
Routes.rb
LootApp::Application.routes.draw do
get "password_resets/new"
get "sessions/new"
get "static_pages/home"
get "static_pages/help"
resources :sessions
resources :password_resets
resources :email_activations
resources :users do
collection do
get :accept_invitation
end
end
root to: 'static_pages#home'
match "sign_up", to: "users#new"
match '/help', to: 'static_pages#help'
match '/log_in', to: 'sessions#new'
match '/log_out', to: 'sessions#destroy'
Application.html.haml
- if current_user
= link_to "log out", log_out_path
- if current_user.admin?
# your admin
- else
= link_to "My account", user_path
- else
= link_to "log in", log_in_path
Users controller
class UsersController < ApplicationController
before_filter :admin_and_user, only: [:destory, :edit, :show]
def show
#user = User.find(params[:id])
end
rake routes
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
just
<%= link_to current_user.name, current_user%>
The current answer is the best solution, but just to elaborate: The problem that was causing an error in your code was that you needed to specify which user the link should link to. So instead of just user_path should you do like this:
= link_to "My account", user_path(current_user)
A shortcut for this is (as shown in the current answer by #Muntasim)
= link_to "My account", current_user
I'm new to RoR and have been working my way through the Hartl tutorial (which has been great). I've followed up through Chapter 9 successfully (tweaking things a bit since my ultimate goal is not to make a microposts site). At that point, I decided that I would like to add a 'remember me' check box and reset password functionality to my app, so I bounced over to the railscast tutorial (as suggested by Hartl). The check box went very smoothly, but I've hit a brick wall with the password reset section. It's been one error after the next. I have to admit that I couldn't help myself and tweak a little - I tried to use theform_for syntax instead of the form_tag syntax. I've gotten as far as being able to submit an email address, but then I get a No route matches [POST] "/reset_password/new" message. I've spent the last two days reading similar posts on stackoverflow and trying out the suggestions, but I just can't seem to come up with something that works. Please help!
Here's the nitty gritty:
My password reset view is located at /app/views/reset_password/new.html.erb:
<% provide(:title, 'Reset Password') %>
<h1>Reset Password</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for #user, url: new_reset_password_path do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.submit "Reset Password", class: "btn btn-large btn-methyl" %>
<% end %>
</div>
</div>
My controller is located at /app/controllers/reset_password_controller.rb:
class ResetPasswordController < ApplicationController
def new
#user = User.new
end
def show
end
def create
#user = User.find_by_email(params[:email].downcase)
user.send_password_reset if user
redirect_to root_path, notice: "Email sent with password reset instructions."
end
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
def update
#user = User.find_by_password_reset_token!(params[:id])
if #user.reset_password_sent_at < 2.hours.ago
redirect_to_new password_reset_path, alert: "Reset password request has expired."
elsif #user.update_attributes(params[:user])
redirect_to root_path, notice: "Password has been reset!"
else
render :edit
end
end
end
My routes are located at /config/routes.rb:
Methylme::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :reset_password
root to: 'static_pages#home'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
.
.
.
end
Finally, $ rake routes reports the following:
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
reset_password_index GET /reset_password(.:format) reset_password#index
POST /reset_password(.:format) reset_password#create
new_reset_password GET /reset_password/new(.:format) reset_password#new
edit_reset_password GET /reset_password/:id/edit(.:format) reset_password#edit
reset_password GET /reset_password/:id(.:format) reset_password#show
PUT /reset_password/:id(.:format) reset_password#update
DELETE /reset_password/:id(.:format) reset_password#destroy
root / static_pages#home
signup /signup(.:format) users#new
signin /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
help /help(.:format) static_pages#help
about /about(.:format) static_pages#about
contact /contact(.:format) static_pages#contact
Thanks in advance for your help!
I don't think you want to link to new_reset_password_path (new) in your password reset view, but to reset_password_path (create), which does send the reset password email.
If your routes don't do what you expect (for instance, the create route does not have an associated xxx_path name) you should simply declare them individually, with
post '/reset_password', to: 'reset_password#create', as: 'send_reset_password' # for example
...
This is one of the best authentication tutorial by Ryan,
http://railscasts.com/episodes/250-authentication-from-scratch-revised
I feel like I have everything I need in my routes.rb, my controller, and my controller spec, but for some reason I'm still getting a routing error (ActionController::RoutingError). Here's my controller:
class HunchController < ActionController::Base
protect_from_forgery
def results
auth_token_key = params[:auth_token_key]
user_id = params[:user_id]
#user = User.create!
#user.auth_token = #user.get_auth_token(auth_token_key, user_id)
#recommended_books = #user.get_recommended_books(#user.auth_token)
end
end
Here's my controller spec:
require 'spec_helper'
describe HunchController do
describe "POST 'results'" do
before do
#params = {
:auth_token_key => "my auth token",
:user_id => "my user id"
}
end
it "succeeds" do
post :results, #params
response.should be_success
end
end
end
And here's my routes.rb:
MyApplicationName::Application.routes.draw do
root :to => 'hunch#index'
resources :users
post 'hunch/results' => "hunch#results"
match '/results' => 'hunch#results'
end
EDIT: Here's my rake routes output:
root / {:controller=>"pages", :action=>"index"}
hunch_results POST /hunch/results(.:format) {:controller=>"hunch", :action=>"results"}
results /results(.:format) {:controller=>"hunch", :action=>"results"}
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
EDIT #2: I'm getting this error with my users#show test too. Here's the actual error:
1) UsersController#show succeeds
Failure/Error: get :show
ActionController::RoutingError:
No route matches {:controller=>"users", :action=>"show"}
# ./spec/controllers/users_controller_spec.rb:13:in `block (3 levels) in <top (required)>'
Ok, I got the same problem when gem journey was updated to the latest version. And find that if you got a route like this:
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
which have a param (id in this case), you necessarily need to render a link in template or use a user_path/user_url variables in controller with param too, so in your templates try to find:
<%= link_to "linkname", user_path %>
and replace by
<%= link_to "linkname", user_path(#user) %>
or search in any controller for the user_path/user_url usage and replace them by user_path(#user)/user_url(#user) accordingly.