Michael Hartl Chapter 10: password/activate email link - ruby-on-rails

I am going through Michael Hartl's tutorial and am stuck on the very end of Chapter 10. When I click "I forgot my password" - the email sends successfully. However the "Reset Password" link, directs me back to the home page, rather then the reset password page.
In views/password_resets/edit.html.rb
<% provide(:title, 'Reset password') %>
<h1>Reset password</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user, url: password_reset_path(params[:id])) do |f| %>
<%= render 'shared/error_messages' %>
<%= hidden_field_tag :email, #user.email %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Update password", class: "btn btn-primary" %>
<% end %>
</div>
</div>
mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "noreply#example.com"
def account_activation(user)
#user = user
mail to: user.email, subject: "Account activation"
end
en.user_mailer.password_reset.subject
#
def password_reset(user)
#user = user
mail to: user.email, subject: "Password reset"
end
end
views/user_mailer/password_reset.html.erb
<h1>Password reset</h1>
<p>To reset your password click the link below:</p>
<%= link_to "Reset password", edit_password_reset_url(#user.reset_token,
email: #user.email) %>
<p>This link will expire in two hours.</p>
<p>
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.
</p>
In models/users.rb
# Sets the password reset attributes.
def create_reset_digest
self.reset_token = User.new_token
update_attribute(:reset_digest, User.digest(reset_token))
update_attribute(:reset_sent_at, Time.zone.now)
end
# Sends password reset email.
def send_password_reset_email
UserMailer.password_reset(self).deliver_now
end
# Returns true if a password reset has expired.
def password_reset_expired?
reset_sent_at < 2.hours.ago
end
config/routes.rb
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
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]
end
Please let me know if there is anything else I can provide to help.

I spent hours trying to figure this out, and finally discovered why I was having this problem. First of all, take a look at the routes file for this chapter Michael has on github here: github
My problem was simple. I hadn't authenticated the user for which I was trying to reset the password, thus I wasn't a valid user and couldn't reset my password.

Mr. Hartl has his routes like so:
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]
end
I think your extra entries are short-circuiting the intended routes.

Related

Delete subscription with a form Rails 4

I'm trying to have subscribers unsubscribe via a delete form where they enter their email and then submit and then delete the subscription. Not sure why this isn't working. I've tried a number of things via my controller. Would love some suggestions or alternatives.
Currently getting this error
Couldn't find Subscription without an ID
Subscriptions controller
def destroy
#subscriptions = Subscription.all
#subscription = #subscriptions.find(params[:id])
if #subscription.email == params[:email]
#subscription.destroy
flash[:notice] = "You have been unsubscribed"
redirect_to root_path
else
end
end
Routes
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
get 'users/new'
resources :posts
root 'static_pages#new_home'
resources :subscriptions, only: [:new, :create, :edit, :update, :show, :destroy]
get '/home' => 'static_pages#home'
get 'subscriptions' => 'subscriptions#show'
delete 'subscriptions' => 'subscriptions#destroy'
get '/about' => 'static_pages#about'
get '/author' => 'static_pages#author'
get '/contact' => 'static_pages#contact'
get '/book' => 'static_pages#book'
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 :posts do
resources :comments
end
end
Unsubscribe partial in subscriptions view
<%= form_for #subscription, method: :delete do |f| %>
<div class="row">
<h2>Unsubscribe</h2>
</div>
<div class="row newsletter">
<form method="post" action="#" class="contact-form">
<div class="row email-label">
<%= f.label :email, :class => 'label-email' %>
<%= f.email_field :email %>
</div>
<div class="row">
<%= f.submit 'Unsubscribe', :class => 'btn-full-subscribe' %>
</div>
</form>
</center
<% end %>
I've tried a number of things with no luck. Help would be appreciated. Thanks. Subscriptions are not related to User model.
This line #subscription = #subscriptions.find(params[:email]) is causing the issue.
Try #subscription = #subscriptions.find_by_email(params[:email]) or better yet, use the id #subscription = #subscriptions.find(params[:id]).
ActiveRecord::find only uses ids: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find.
Problem is here
#subscription = #subscriptions.find(params[:email])
because find uses id to fetch the record if you want to fetch by any other field use find_by_"attribute_name", Replace it with
#subscription = Subscription.find_by_email(params[:email])
Or no need to write down extra code. No need to fetch all the subscriptions. To delete use
#subscription = Subscription.find_by_email(params[:email])
or
#subscription = Subscription.find(params[:id])
if #subscription.destroy
flash[:notice] = "You have been unsubscribed"
redirect_to root_path
end

partials not displaying on new charges controller (stripe)

I made a new controller to integrate Stripe Checkout, but it's acting as its own entire website and none of my partials (_header, _footer) are displaying.
The current setups is straight from their tutorial https://stripe.com/docs/checkout/guides/rails
Charges Controller
class ChargesController < ApplicationController
def new
end
def create
# Amount in cents
#amount = 100
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken],
:plan => "tier1",
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
Routes
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
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'
get 'charges' => 'charges#new'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :charges
end
/layouts/charges.html.erb (controller view)
<% provide(:title, 'Edit Billing') %>
<%= yield %>
views/charges/new.html.erb (form with Stripe Checkout on it)
<%= form_tag charges_path do %>
<article>
<% if flash[:error].present? %>
<div id="error_explanation">
<p><%= flash[:error] %></p>
</div>
<% end %>
<label class="amount">
<span>Amount: $1.00</span>
</label>
</article>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
data-description="Tier 1 Monthly Subscription"
data-amount="100"
data-locale="auto"
data-image="images/marketplace.png"
data-name="Pallet Tier 1"
data-description="Tier 1 Monthly Subscription"
data-label="Join" >
</script>
views/charges/create.html.erb (redirect after successful charge)
<% provide(:title, 'Edit Billing') %>
<h2>Thanks, you paid <strong>$1.00</strong>!</h2>

getting No route matches [POST] "/login/log_in"

im using gem parse-ruby-client and im trying to create a login. and when the login is successful then i want to go to a welcome#index
here is my login_controller.rb
class LoginController < ApplicationController
def index
end
def log_in
#user = Parse::User.authenticate(params[:user][:username], params[:user][:password])
end
end
index.html.erb
<div class="Log_in_Form">
<h4><center>Log in with your existing "app_name" account</center></h4>
<%= form_for(:user, :url => {:controller => 'login', :action => 'log_in'}) do |f| %>
<center><p> Username:</br> <%= f.text_field :username%> </p></center>
<center><p> Password:</br> <%= f.password_field :password%></p></center>
<center><h4><%= f.submit :Login %></h4></center>
<% end %>
</div>
routes.rb
Rails.application.routes.draw do
get 'welcome/index'
root 'login#index'
get 'login/log_in' => 'login#log_in'
end
you need to have an post route or your login. change your routes to this one (if you need the get route also)
Rails.application.routes.draw do
get 'welcome/index'
root 'login#index'
get 'login/log_in' => 'login#log_in'
post 'login/log_in' => 'login#log_in'
end
or change
get 'login/log_in' => 'login#log_in'
to
match 'login/log_in' => 'login#log_in', via: [:get, :post]

Ruby on Rails, Promote to Admin function

I'm quite new to Ruby on Rails and I'm trying to learn a bit, so I tried making a new function.
The error I'm getting right now is:
ActionController::RoutingError (No route matches [POST] "/users/2"):
I'm trying to make a function to promote other users to admin, which is only possible as an admin.
My users_controller.rb contains:
def promote
if !User.find(params[:id]).admin?
User.find(params[:id]).toggle!(:admin)
flash[:success] = "User is promoted to admin."
redirect_to users_url
else
flash[:danger] = "Admins can't demote other admins."
redirect_to users_url
end
end
My _user.html.erb contains:
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
<% if !user.admin? %>
<br /> <%= link_to "Delete User", user, method: :delete,
data: { confirm: "You sure?" } %>
| <%= link_to "Promote to Admin", user, method: :promote,
data: { confirm: "You sure?" } %>
<% end %>
<% end %>
And then we have my routes.rb, which contains:
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
get 'users/new'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
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 :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :relationships, only: [:create, :destroy]
end
I can't exactly find what's going wrong. Some advice would be awesome!
def promote
#user = User.find(params[:id])
if #user.admin?
#user.toggle!(:admin)
flash[:success] = "User is promoted to admin."
redirect_to users_path
else
flash[:notice] = "Admins can't demote other admins."
redirect_to users_path
end
end
<%= link_to #user.name, #user %>
<% if current_user.admin? && !current_user?(#user) %>
<% if !#user.admin? %>
<br />
<%= link_to "Delete User", #user, method: :delete, data: { confirm: "You sure?" } %>
| <%= link_to "Promote to Admin", promote_users_path(user), method: :put, data: { confirm: "You sure?" } %>
<% end %>
<% end %>
in route
resources :users do
member do
get :following, :followers,
put :promote
end
end
or
match '/users', to: 'users#promote', via: :put

Routing Error: uninitialized constant Sessions

I'm following this Ruby Railcasts episode to get some simple auth going, and I'm getting the error uninitialized constant Sessions when I navigate to the login page. I've checked my classes and the names are proper, which seems to be the problem most people report. Any idea what might be happening here?
The name of my controller file is sessions_controller.rb and the code is as follows:
class SessionsController < ApplicationController
def new
end
def create
user = User.authenticate(params[:email], params[:password])
if user
session[:user_id] = user.id
redirect_to root_url, :notice => 'Logged In!'
else
flash.now.alert = 'Invalid email or password'
render 'new'
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => 'Logged Out!'
end
end
routes.rb file:
Albumtracker::Application.routes.draw do
get "login" => "sessions/new", :as => "login"
get "logout" => "sessions/destroy", :as => "logout"
get "signup" => "users/new", :as => "sign_up"
root :to => 'users#new'
resources :users
resources :sessions
get "pages/index"
end
sessions/new view file:
<h1>Log in</h1>
<%= form_tag sessions_path do %>
<p>
<%= label_tag :email %><br />
<%= text_field_tag :email, params[:email] %>
</p>
<p>
<%= label_tag :password %><br />
<%= password_field_tag :password %>
</p>
<p class="button"><%= submit_tag "Log in" %></p>
<% end %>
You have typos in your routes. / should be # when specifying a controller and action. Your routes should look like this:
get "login" => "sessions#new", :as => "login"
get "logout" => "sessions#destroy", :as => "logout"
get "signup" => "users#new", :as => "sign_up"
When you use / in your route the preceding portion is matched to a namespace. So from "sessions/new" the router was trying to locate a controller named Sessions::NewController. Since the namespace Sessions doesn't exist in your app, you got the uninitialized constant error.

Resources