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.
Related
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.
Hey guys I am using Rails 5. I am trying to let my users edit there info, password etc but when I go to this route.
http://0.0.0.0:3000/users/edit/1
The error I get is
No route matches [GET] "/users/edit/1"
I do have a user with an ID of 1 and I have checked in my rails console to verify.
I have an edit template, and the edit controller and the edit method in the controller but its just not working. What am I doing wrong? All help is welcome, thank you!
ROUTES
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'pages#home'
get 'pages/tierlist', to: 'pages#tierlist'
resources :articles
get 'signup', to: 'users#new'
resource :users, except:[:new]
end
USERSCONTROLLER
class UsersController <ApplicationController
def new
#user = User.new
end
def create
#user = User.create(user_params)
if #user.save
flash[:success] = "Welcome to the OP-OR-Nah Community #{#user.username}"
redirect_to articles_path
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:username, :email, :password)
end
end
edit.html.erb
<h1>Edit your info</h1>
Also when I rake routes this is what I get back
rake routes |grep edit
edit_article GET /articles/:id/edit(.:format) articles#edit
edit_users GET /users/edit(.:format) users#edit
You have a typo in your file that is breaking the route.
Should be
resources :users, except: [:new]
That route typically should look like
"/users/:id/edit"
when you run rake:routes.
Default url for edit is pluralize_model_name/id/edit so users/1/edit. Anyway, you wrote resource and not resources so I think you have not that route. resource is a different method that generate something like
GET /user/new
GET /user
GET /user/edit
PATCH/PUT /user
DELETE /user
POST /user
Running the provided spec fails, and I think it might be related to the url parameters, being territories/:id/.
Error received :
1) territories/edit.html.erb shows a form with the data already in it
Failure/Error: <%= form_for(territory, remote: true) do |territory_form| %>
ActionView::Template::Error:
No route matches {:action=>"show", :controller=>"territories", :format=>nil, :id=>nil, :locale=>#<Territory id: 2, name: "Territory 4", lent_on: "2015-12-21", returned_on: "2015-12-21", lent_to: 6, created_at: "2015-12-23 10:04:15", updated_at: "2015-12-23 10:04:15">} missing required keys: [:id]
I'm working with form_for. I find it a bit weird that I receive an error about the url parameter in my view, while I'm not having anything directly related to it in the view code.
I've put the controller code as wel, just for clarity.
Can someone guide me how to either fix this or how to properly test this
edit.html.erb
<h1>Territories#edit</h1>
<p>Find me in app/views/territories/edit.html.erb</p>
<%= render partial: "territory_form", locals: { territory: #territory } %>
edit.html.erb_spec.rb
require 'rails_helper'
RSpec.describe "territories/edit.html.erb", type: :view, territories:true do
before(:each) do
#territory = create(:territory)
render
end
it "shows a form with the data already in it" do
puts "Body: #{rendered}"
expect(rendered).to have_css("label", :text => "Name")
expect(rendered).to have_css "input[value*='#{#territory.name}']"
end
end
routes.rb
Prefix Verb URI Pattern Controller#Action
sessions_new GET (/:locale)/sessions/new(.:format) sessions#new {:locale=>/en|nl/}
sign_up_new GET (/:locale)/sign_up/new(.:format) sign_up#new {:locale=>/en|nl/}
users GET (/:locale)/users(.:format) users#index {:locale=>/en|nl/}
edit_user GET (/:locale)/users/:id/edit(.:format) users#edit {:locale=>/en|nl/}
user GET (/:locale)/users/:id(.:format) users#show {:locale=>/en|nl/}
PATCH (/:locale)/users/:id(.:format) users#update {:locale=>/en|nl/}
PUT (/:locale)/users/:id(.:format) users#update {:locale=>/en|nl/}
DELETE (/:locale)/users/:id(.:format) users#destroy {:locale=>/en|nl/}
register GET (/:locale)/register(.:format) users#new {:locale=>/en|nl/}
POST (/:locale)/register(.:format) users#create {:locale=>/en|nl/}
login GET (/:locale)/login(.:format) sessions#new {:locale=>/en|nl/}
POST (/:locale)/login(.:format) sessions#create {:locale=>/en|nl/}
logout DELETE (/:locale)/logout(.:format) sessions#destroy {:locale=>/en|nl/}
overview GET (/:locale)/user/overview(.:format) dashboard#index {:locale=>/en|nl/}
territories GET (/:locale)/admin/territories(.:format) territories#index {:locale=>/en|nl/}
POST (/:locale)/admin/territories(.:format) territories#create {:locale=>/en|nl/}
new_territory GET (/:locale)/admin/territories/new(.:format) territories#new {:locale=>/en|nl/}
edit_territory GET (/:locale)/admin/territories/:id/edit(.:format) territories#edit {:locale=>/en|nl/}
territory GET (/:locale)/admin/territories/:id(.:format) territories#show {:locale=>/en|nl/}
PATCH (/:locale)/admin/territories/:id(.:format) territories#update {:locale=>/en|nl/}
PUT (/:locale)/admin/territories/:id(.:format) territories#update {:locale=>/en|nl/}
DELETE (/:locale)/admin/territories/:id(.:format) territories#destroy {:locale=>/en|nl/}
GET /:locale(.:format) sessions#new
root GET / sessions#new
territories_controller.rb
class TerritoriesController < ApplicationController
def index
#territories = Territory.all.order(:name) #Must be changed to use pagination
end
def new
#territory = Territory.new
end
def import
end
def create
#territory = Territory.new(create_params)
if (!#territory.save)
render action: :create and return
end
render action :new
end
def show
end
def edit
#territory = Territory.find(edit_params)
end
def update
territory_params = update_params
#territory = Territory.find(territory_params[:id])
if (!#territory || !#territory.persisted?)
render index and return
end
#territory.update(territory_params[:territory])
end
def destroy
end
private
def create_params
params.require(:territory).permit(:name)
end
def edit_params
params.require(:id)
end
def update_params
id = params.require(:id)
territory = params.require(:territory).permit(:name)
{:id => id, :territory => territory}
end
end
territory_form.html.erb
<%= form_for(territory, remote: true) do |territory_form| %>
<p>
<%= territory_form.label :name %>
<%= territory_form.text_field :name %>
</p>
<%= territory_form.submit %>
<% end %>
Made it into a gist
def edit
#territory = Territory.find(edit_params)
end
Should just be
def edit
#territory = Territory.find(params[:id])
end
My question has to do with mapping to controllers/actions using named routes. I am trying to map '/profile' to 'customers#show'. My routes file looks like this:
root :to => 'pages#home'
## named routes
match "profile" => "customers#show", :as => 'profile'
match 'signin' => 'sessions#new', :as => 'signin'
match 'signout' => 'sessions#destroy', :as => 'signout'
resources :customers do
member do
get 'add_card'
post 'submit_card'
end
end
resources :payments, :only => [:show, :new]
delete 'payments/delete_recurring_payment'
post 'payments/submit_non_recurring'
post 'payments/submit_recurring'
resources :sessions, :only => [:create, :destroy, :new]
Running 'rake routes' gives me this:
root / pages#home
profile /profile(.:format) customers#show
signin /signin(.:format) sessions#new
signout /signout(.:format) sessions#destroy
add_card_customer GET /customers/:id/add_card(.:format) customers#add_card
submit_card_customer POST /customers/:id/submit_card(.:format) customers#submit_card
customers GET /customers(.:format) customers#index
POST /customers(.:format) customers#create
new_customer GET /customers/new(.:format) customers#new
edit_customer GET /customers/:id/edit(.:format) customers#edit
customer GET /customers/:id(.:format) customers#show
PUT /customers/:id(.:format) customers#update
DELETE /customers/:id(.:format) customers#destroy
new_payment GET /payments/new(.:format) payments#new
payment GET /payments/:id(.:format) payments#show
Here is where I'm stumped. When I go to localhost:3000/profile I get a routing error saying this:
No route matches {:action=>"edit", :controller=>"customers"}
This seems odd because there is indeed a route to 'customers#edit' due to my declaring customers as a resource.
However, when I go to 'localhost:3000/signin' I get routed to 'customers#show' which is where I want '/profile' to route to.
It seems like my routes are 'one off' in my routes file but I have no idea why. Any help would be much appreciated.
Thanks
UPDATE 1: Adding my Customers Controller
class CustomersController < ApplicationController
layout "payments_layout"
def show
#customer = current_user
get_account_info(#customer)
get_payment_history(#customer, 10)
end
def new
#title = 'Create an account'
#customer = Customer.new
end
def edit
#customer = current_user
get_account_info(#customer)
end
def update
#customer = current_user
if #customer.update(params[:customer])
redirect_to #customer
else
#card_message = "Use this form to add a credit card to your account. You must have a credit card associated with your account in
in order to make payments on our system."
get_account_info(#customer)
render 'edit'
end
end
def create
#customer = Customer.new(params[:customer])
if #customer.save_and_get_stripe_id
sign_in(#customer)
redirect_to #customer
else
#title = 'Create an account'
render 'new'
end
end
def add_card
#customer = current_user
get_account_info(#customer)
#card_message = "Use this form to add a credit card to your account. You must have a credit card associated with your account in
in order to make payments on our system."
end
def submit_card
#customer = current_user
res = #customer.add_or_update_card(params)
if res
redirect_to #customer
else
#error = res
customer.get_account_info(#customer)
render 'add_card'
end
end
end
Check your views.
Do you have a link to edit your user profile?
It seems like you actually route to the right controller and action but have some links that rake can't route, e.g. you don't pass the ID to your edit_customer_path link.
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)