RSpec routes recognision - ruby-on-rails

I have an interesting situation which leaves me scratching my head.
I've created a controller (without a model) to generate password resets. I've defined a RESTful route to the controller:
routes.rb
resources :password_resets
I've created some action on the controller, in particular my edit action:
password_resets_controller.rb
class PasswordResetsController < ApplicationController
# code omitted
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
# code omitted
end
The user can access the edit from the email that I send to the user:
password_reset.html.haml
%p To reset your password, click the URL below.
= edit_password_reset_url(#user.password_reset_token)
So far so good, I've managed to use the code.
Then I have the spec that tests my mailer:
describe "password reset" do
let(:user) { FactoryGirl.create(:user) }
let(:mail) { UserMailer.password_reset(user) }
it "sends user password reset url" do
mail.to.should eq([user.email])
end
end
Surprisingly, I get the following:
Failure/Error: let(:mail) { UserMailer.password_reset(user) }
ActionView::Template::Error:
No route matches {:action=>"edit", :controller=>"password_resets"}
# ./app/views/user_mailer/password_reset.html.haml:5:in `_app_views_user_mailer_password_reset_html_haml__1760284087840822602_11954840'
# ./app/mailers/user_mailer.rb:7:in `password_reset'
Yet there is a route match, at least by looking at my routes:
password_resets GET /password_resets(.:format) password_resets#index
POST /password_resets(.:format) password_resets#create
new_password_reset GET /password_resets/new(.:format) password_resets#new
edit_password_reset GET /password_resets/:id/edit(.:format) password_resets#edit
password_reset GET /password_resets/:id(.:format) password_resets#show
PUT /password_resets/:id(.:format) password_resets#update
DELETE /password_resets/:id(.:format) password_resets#destroy
What could possible go wrong in my test/routes?
Many thanks.

Check if Factory user has password_reset_token. Most likely it is nil, same routing error you can get for any edit_something_url(nil)

Related

ruby on rails tutorial chapter 8 test error

I'm getting two different test errors in Chapter 8.2.1 of Michael Hartl's Ruby on Rails Tutorial. I'm new to Rails, but I have triple checked for syntax errors and anything else I could find. Any help is very much appreciated.
Error Message 1:
ERROR["test_should_get_new", Minitest::Result, 0.9693643249993329]
test_should_get_new#Minitest::Result (0.97s)
NameError: NameError: undefined local variable or method users_new_url' for #<UsersControllerTest:0x00000006e953f8>
test/controllers/users_controller_test.rb:5:inblock in '
Error Message 2:
ERROR["test_invalid_signup_information", Minitest::Result, 0.8977870759990765]
test_invalid_signup_information#Minitest::Result (0.90s)
ActionController::RoutingError: ActionController::RoutingError: No route matches [POST] "/signup"
test/integration/users_signup_test.rb:8:in block (2 levels) in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:7:inblock in '
Routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
end
Sessions Controller:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
# Log the user in and redirect to the user's show page.
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
end
end
Users Controller:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Welcome to your new profile!"
redirect_to #user
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
Users controller test
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
test "should get new" do
get users_new_url
assert_response :success
end
end
Users Signup Test
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, params: { user: { name: "",
email: "user#invalid",
password: "foo",
password_confirmation: "bar" } }
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
assert_select 'form[action="/signup"]'
end
test "valid signup information" do
get signup_path
assert_difference 'User.count', 1 do
post users_path, params: { user: { name: "Example User",
email: "user#example.com",
password: "password",
password_confirmation: "password" } }
end
follow_redirect!
assert_template 'users/show'
assert_not flash.nil?
end
end
In your users_controller_test, the code doesn't know what users_new_url is. This is probably because that route doesn't exist. You will most likely have to do something like get new_user_path, but you can find out by typing rake routes and getting the list of your available routes.
Here's an example of what rake routes will output:
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
You can reference a named path by appending _path to the name. i.e. users_path will map to the "users#index"controller and method.
rake routes will also help for your second problem, which is that you do not have a route defined for POST /signup -- you have a GET /signup.
So, you'll need to add a line like:
post '/signup', to: 'users#create'
This route will map to your UsersController's #create method, which I see you have in your code.

Rails application route cannot access from Grape API

I'm requesting for any user from a different rails application. I'm using grape gem. The below code is the requested user's information sending controller action.
but unfortunately it is showing error:
NoMethodError (undefined method `profile_url' for #<Grape::Endpoint:0xdadef8c>):
What is the problem? My rake routes showing the url does exists.
module V1
class User < Grape::API
version 'v1', using: :path
format :json
prefix :api
resource :user do
desc "find any user"
params do
requires :email, type: String
requires :password, type: String
end
get :create do
user = User.find_by_email(params[:email])
if user.present?
if user.valid_password?(params[:password])
{user: user, profile_url: profile_url(user.profile)}
else
{:notice => "Invalid password for email: #{params[:email]}"}
end
else
{:notice => "No user found with email: #{params[:email]}"}
end
end
end
end
end
rake routes | grep profile:
profiles GET /profiles(.:format) profiles#index
POST /profiles(.:format) profiles#create
new_profile GET /profiles/new(.:format) profiles#new
edit_profile GET /profiles/:id/edit(.:format) profiles#edit
profile GET /profiles/:id(.:format) profiles#show
PATCH /profiles/:id(.:format) profiles#update
PUT /profiles/:id(.:format) profiles#update
DELETE /profiles/:id(.:format) profiles#destroy
Make sure you mounted the resource properly.
You may need something like this:
mount API::v1::User
See more about mounting here
Also, take a look at this post. Might be helpful to see how you can mount your resource while using Grape gem.
You can do it like this:
Rails.application.routes.url_helpers.profile_url(user.profile)

How to access devise token auth registration controller?

I am using Devise auth token gem for authenticating some parts of my rails app. But when I try to create a new user with the registration path, it is giving me the following error{"errors":["Authorized users only."]}.
Here is the rspec code that I am using for the test,
it 'creates a user using email/password combo' do
post api_user_registration_path, { email: 'xxx', password: 'yyy',password_confirmation: 'yyy'}
puts last_response.body
expect(last_response.body).not_to have_content('error')
end
Additional info: the model name is 'User' and the routes looks like,
namespace :api do
scope :v1 do
mount_devise_token_auth_for 'User', at: 'auth'
end
end
I understand that the devise is expecting the user to be authenticated before accessing this path, but this being the user registration, it needs to be outside the authentication. Can you suggest a solution for this? Is there any configuration that I am missing here?
Try with:
namespace :api do
namespace :v1 do
mount_devise_token_auth_for 'User', at: '/auth'
end
end
This will create the following routes:
new_api_v1_user_session GET /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#new
api_v1_user_session POST /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#create
destroy_api_v1_user_session DELETE /api/v1/auth/sign_out(.:format) devise_token_auth/sessions#destroy
api_v1_user_password POST /api/v1/auth/password(.:format) devise_token_auth/passwords#create
new_api_v1_user_password GET /api/v1/auth/password/new(.:format) devise_token_auth/passwords#new
edit_api_v1_user_password GET /api/v1/auth/password/edit(.:format) devise_token_auth/passwords#edit
PATCH /api/v1/auth/password(.:format) devise_token_auth/passwords#update
PUT /api/v1/auth/password(.:format) devise_token_auth/passwords#update
cancel_api_v1_user_registration GET /api/v1/auth/cancel(.:format) devise_token_auth/registrations#cancel
api_v1_user_registration POST /api/v1/auth(.:format) devise_token_auth/registrations#create
new_api_v1_user_registration GET /api/v1/auth/sign_up(.:format) devise_token_auth/registrations#new
edit_api_v1_user_registration GET /api/v1/auth/edit(.:format) devise_token_auth/registrations#edit
PATCH /api/v1/auth(.:format) devise_token_auth/registrations#update
PUT /api/v1/auth(.:format) devise_token_auth/registrations#update
DELETE /api/v1/auth(.:format) devise_token_auth/registrations#destroy
api_v1_auth_validate_token GET /api/v1/auth/validate_token(.:format) devise_token_auth/token_validations#validate_token
Also create an controller in app/controllers/api/v1/api_base_controller.rb
class Api::V1::BaseApiController < ActionController::Base
include DeviseTokenAuth::Concerns::SetUserByToken
end
Also add to your file app/controllers/application_controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?

no route matches - rails 4.0

I have a route set up as such:
get 'password reset' => 'password_resets#edit', :as => 'password_reset'
resources :password_resets
I have a controller as such:
class PasswordResetsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user
user.send_password_reset
redirect_to root_url, :notice => 'Email has been sent. Please follow instructions to reset your password.'
else
redirect_to password_resets_path
flash[:error] = 'Sorry but we do not know that email.'
end
end
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
end
I then sent an email off and used letter_opener to view its contents in browser:
No route matches {:controller=>"password_resets", :action=>"edit", :format=>"lYoa1Rh6yfwL2olfwkODnQ"} missing required keys: [:id]
I then did rake routes
password_resets GET /password_resets(.:format) password_resets#index
POST /password_resets(.:format) password_resets#create
new_password_reset GET /password_resets/new(.:format) password_resets#new
edit_password_reset GET /password_resets/:id/edit(.:format) password_resets#edit
GET /password_resets/:id(.:format) password_resets#show
PATCH /password_resets/:id(.:format) password_resets#update
PUT /password_resets/:id(.:format) password_resets#update
DELETE /password_resets/:id(.:format) password_resets#destroy
Why am I getting this error? all my mailer tests are passing ... but trying this in browser means that eaither my mailer tests are lying or something is wrong.
If I try doing a link like:
link_to "Some where", edit_password_reset_url(#user.password_reset_token)
The browser works but the tests fail ... with the same error message.
try
link_to "Some where", edit_password_reset_url(id: #user.password_reset_token)
If user.password_reset_token = lYoa1Rh6yfwL2olfwkODnQ
You should send ID of this password table to the edit action.

RSpec test fails with "No route matches" for resources route

Context
I'm running into a very weird test failure that I can't explain based on my code.
When I run the spec test provided below, it will display the following error:
Failures:
1) GroupsController GET 'index' returns http success
Failure/Error: get 'index'
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"groups"}
# ./spec/controllers/groups_controller_spec.rb:14:in `block (3 levels) in '
Test case
The test case for the controller and routes set in RSpec looks like this:
describe GroupsController do
before :each do
#group = FactoryGirl.create(:group)
#user = FactoryGirl.create(:user)
sign_in #user
end
describe "GET 'index'" do
it "returns http success" do
get 'index'
response.should be_success
end
end
end
Controller under test
I've written a very basic skeleton for my controller based on the test.
Currently it doesn't do a whole lot of stuff.
class GroupsController < ApplicationController
before_filter :authenticate_user!
def index
#groups = current_user.groups
end
end
Routes configured to reach the controller
The routes.rb file looks like this:
NerdCooking::Application.routes.draw do
resources :groups
devise_for :users
root :to => "home#welcome"
end
Routes
groups GET /groups(.:format) groups#index
POST /groups(.:format) groups#create
new_group GET /groups/new(.:format) groups#new
edit_group GET /groups/:id/edit(.:format) groups#edit
group GET /groups/:id(.:format) groups#show
PATCH /groups/:id(.:format) groups#update
PUT /groups/:id(.:format) groups#update
DELETE /groups/:id(.:format) groups#destroy
Question
I have tried changing the route to get "groups" => "groups#index" instead of the resources route and that works, but it's not something I want since I want to use this as a RESTful service as well.
What am I doing wrong here?
Update: Added the routes related to groups.
Okay, apparently my Guard and Spork were acting mean.
Once I restarted Guard/Spork and it all worked as expected. Looking back at the code and configuration there was no reason why stuff was going wrong.
So if anyone else is experiencing this behavior and their config and code check out. Restart!

Resources