action mailer rails ArgumentError in Password_resets#create - ruby-on-rails

I set up a basic sign in, login, sign out format for a rails app and I was going to give it a function so that if a person forgot their password they could get a email back. when I went click on submit password reset I got
Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
Extracted source (around line #3):
1: To reset your password click the URL below.
2:
3: <%= edit_password_reset_url(#user.password_reset_token) %>
4:
5: If you did not request your password to be reset please ignore this email and your password will stay as it is.
Rails.root: /Users/cheatermoves/nightclass/mainproject/project
Application Trace | Framework Trace | Full Trace
app/views/user_mailer/password_reset.text.erb:3:in `_app_views_user_mailer_password_reset_text_erb__3613112772785486465_70118994937040'
app/mailers/user_mailer.rb:6:in `password_reset'
app/models/user.rb:17:in `send_password_reset'
app/controllers/password_resets_controller.rb:7:in `create'
just completed rails cast 250 and was doing 274. Everything was fine until I got this problem.
here is my controllers. Password resets:
class PasswordResetsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
user.send_password_reset if user
redirect_to root_url, :notice => "Email sent with password reset instructions."
end
end
sessions:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
if params[:remember_me]
cookies.permanent[:auth_token] = user.auth_token
else
cookies[:auth_token] = user.auth_token
end
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
def destroy
cookies.delete(:auth_token)
redirect_to root_url, :notice => "Logged out!"
end
end
users:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
session[:user_id] = #user.id
redirect_to root_url, notice: "Thank you for signing up!"
else
render "new"
end
end
end
and application:
class ApplicationController < ActionController::Base
protect_from_forgery
private
def current_user
#current_user ||= User.find_by_auth_token( cookies[:auth_token]) if cookies[:auth_token]
end
helper_method :current_user
end
in environments/development.rb I have
config.action_mailer.default_url_options = { :host => "localhost:3000" }
here is my user model
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_secure_password
validates_presence_of :password, :on => :create
before_create { generate_token(:auth_token) }
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
end
user_mailer.rb file
class UserMailer < ActionMailer::Base
default from: "from#example.com"
def password_reset(user)
#user = user
mail :to => user.email, :subject => "Password Reset"
end
end
anyone know what the problem is and how to fix it? I'm using rails 3.2.14 if anyone is wondering. Thanks!

Didn't read the part where you said that you already set your
config.default_url_options[:host] = "localhost:3000"
my bad, sorry

Related

Rails how to require the current password to allow user update

I am having a rather difficult problem i want to update the user profile only if they submit the current password.I am not using devise.And another post here at stack overflow didn't really help me.
This is my User controller code:
class UsersController < ApplicationController
def new
#user = User.new
end
def show
#user = User.find(params[:id])
#user_posts = #user.posts if #user
if #user
if #user_posts
render 'show.html'
else
render 'show.html'
end
else
render file: 'public/404.html', status: 404, formats: [:html]
end
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to root_path
flash[:notice] = "Successfully Signed up :-)"
else
redirect_to signup_path
flash[:notice] = "You didn't sign up successfully :-("
end
end
def edit
#user = User.find(params[:id])
if current_user.id = #user.id
render 'edit'
else
redirect_to #user
end
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:notice] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
:password == :password_confirmation
private
def user_params
params.require(:user).permit(:user_name, :email, :password, :password_confirmation)
end
end
And this is my user.rb:
class User
has_secure_password
has_many :posts
has_many :comments
def admin?
self.role == 'admin'
end
def moderator?
self.role == 'moderator'
end
end
Please help because I have been working with this for a long time now. And the other solution about this topic here at stack overflow didn't work.
One way is to use virtual attributes
1. The User model
class User < ActiveRecord::Base
attr_accessor :current_password
end
2. The form
add the current_password attribute to the form as a text_field input
3. The UsersController
def update
#user = User.find params[:id]
if #user.authenticate(update_params[:current_password])
# update the user
# maybe check if the data are valid
#user.update(update_params)
else
flash[:warning] = "Please provide your password"
#user.errors.add :current_password, "invalid"
render :edit
end
end
def update_params
params.require(:user).permit(:current_password, :email)
end
First, you have a problem in your edit action:
current_user.id = #user.id
That assigns #user.id to current_user.id - you wanted == to test that it's the correct User. You should put a similar check on update, and probably extract it into a before_action so you can easily apply it anywhere you want to.
To check that the password is present, add it to your form like any other field and then get it out of params to verify it. That would look something like this:
class UsersController < ApplicationController
def update
encrypted = encrypt(params[:password]) # Using whatever your mechanism is
if encrypted == #user.encrypted_password
# Update the user
else
flash[:notice] = 'Password is required to update user information.'
redirect_to edit_user(path(#user))
end
end
end

RoR - NoMethodError, undefined method

I have created an app with simple login authentication, it is actually a twitter clone. The user logs in and access the pages, etc.
But when the user posts something from there profile. It gives an error
NoMethodError in RibbitsController#create
undefined method `id=' for nil:NilClass
The error is around line 5:
class RibbitsController < ApplicationController
def create
#ribbit = Ribbit.create(user_ribbits)
#ribbit.userid = current_user.id
if #ribbit.save
redirect_to current_user
else
flash[:error] = "Problem!"
redirect_to current_user
end
end
private
def user_ribbits
params.require(:ribbit).permit(:content, :userid)
end
end
The request given to app:
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"dwVmjDNO4GOowphGFgChMDBxBfvka+M/xSUHvJMECzwxtv4NF6OuWtiaX74NLz91OwQJ9T9+wm7yMiPQ0BLpGA==",
"ribbit"=>{"content"=>"hi. test.\r\n"},
"commit"=>"Ribbit!"}
The sessions controller:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_username(params[:username])
if user && user.authenticate(params[:password])
session[:userid] = user.id
redirect_to rooturl, notice: "Logged in!"
else
flash[:error] = "Wrong Username or Password."
redirect_to root_url
end
end
def destroy
session[:userid] = nil
redirect_to root_url, notice: "Logged out."
end
end
The users controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.create(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to #user, notice: "Thank you for signing up!"
else
render 'new'
end
end
def show
#user = User.find(params[:id])
#ribbit = Ribbit.new
end
private
def user_params
params.require(:user).permit(:name, :username, :email, :password, :password_confirmation, :avatar_url)
end
end
And the application controller
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
I would really appreciate it if you guys would help!
Thanks.
You're trying to assign current_user.idto #ribbit.userid without ensuring that current_user is set. 'current_user' would be set only if a user has been previously saved before.
Therefore, you need either to make sure that an authenticated user is trying to create a Ribbit, or if you consider the userid as a non mandatory field, you can simply change your line 5 by:
#ribbit.userid = current_user.id unless current_user.blank?
If you only want authenticated user to create Ribbits, then consider using a gem to handle authentication such as Devise. You could then use before_filter :authenticate_user! in your controller to make sure users are properly authenticated.

Why is this Mailer giving an error after applying validations?

The error is coming in the create method user mailer section.
I am trying to resolve it, but nothing happens.
How can it be resolved? I come when I apply the validations.
The error is: Expected a URI like gid://app/Person/1234: #<URI::GID gid://email>
My mailer controller:
class UserMailer < ApplicationMailer
def welcome_email(user)
#user = user
#url = 'http:3000//example.com/login#u'
mail(to: #user.email, subject: 'Welcome to My Awesome Site')
end
end
My user controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
#user.save
UserMailer.welcome_email(#user).deliver_later[here the error come about the invalid url]
render 'token'
end
def verify
#user = User.authenticate(params[:auth_token])
if #user
redirect_to edit_user_path(#user)
else
flash.now.alert = "Invalid email or password"
render 'token', :alert =>"Invalid email or password"
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to new_login_path
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :dob, :email,
:password, :confirm_password, :auth_token)
end
end
You are trying to pass the Mailer an unpersisted object, ie. an object that was not saved to the database.
From your code, that means that the previous #user.save statement failed probably due to a validation error. In that case, you don't want to send the email anyway.
Change your create action like this:
def create
#user = User.new(user_params)
if #user.save
UserMailer.welcome_email(#user).deliver_later
render 'token'
else
flash[:error] = 'User was not saved'
render 'new'
end
end

Rails password_reset recordnotfound

I am getting an error when I pass in my url to reset my password for example: localhost:3000/password_reset/SADASIJDSIDJ1231231/edit <---- gives me ActiveRecord::RecordNotFound and its pointing at in my password_reset_controller
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
This is my application controller (notice the "include SessionsHelper")
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
#om du lägger till kod här kmr inte sessions funka när du är inloggad wtf???
#tog bort detta protect_from_forgery with: :exception
include SessionsHelper
protect_from_forgery
private
def current_user
#current_user ||= User.find_by_auth_token(cookies[:auth_token]) if cookies[:auth_token]
end
helper_method :current_user
end
This is my password_reset_controller
class PasswordResetsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
user.send_password_reset if user
redirect_to root_url, :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.password_reset_sent_at < 2.hours.ago
redirect_to new_password_reset_path, :alert => "Password reset has expired."
elsif #user.update_attributes(params.permit![:user])
redirect_to root_url, :notice => "Password has been reset!"
else
render :edit
end
end
end
HOW I SOLVED IT:
So thanks to jorge I knew password_reset_token wasn't generated in the database. So I went back to my model/user.rb
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
I added back "save!" it was "save" before. Then I got another error saying password can't be blank.
So I deleted these two lines
# validates :password, length: { minimum: 6 }, presence: true
#validates :password_confirmation, presence: true
Instead I added this line
validates_presence_of :password, :on => :create
Now everything works. Thanks for your patience jorge. I owe u one big.
Did you check in the database that the a user exists with password reset token "SADASIJDSIDJ1231231"?
Looks like following line is not finding a user:
#user = User.find_by_password_reset_token!(params[:id])
Please include your User class - the send_password_reset method may not be saving the token correctly.

I am using rails cast omniauth and i get this error

I am using Mongodb as database in rails and i got error when using /auth/linkedin/callback
NoMethodError in AuthenticationsController#create undefined method []' for nil:NilClass Rails.root: /home/prem/Music/heronhrm Application Trace | Framework Trace | Full Trace app/models/user.rb:57:in apply_omniauth' app/controllers/authentications_controller.rb:19:in `create'
Also when i remove self.email = omniauth['user_info']['email'] if email.blank? from usermodel then the validation errors arises in
users/sign_up Email can't be blank
I want to implement for twitter,linkdin and facebook.
my authentication.rb
class Authentication
include Mongoid::Document
belongs_to :user
field :user_id, :type => String
field :provider, :type => String
field :uid, :type => String
def self.find_by_provider_and_uid(provider, uid)
where(provider: provider, uid: uid).first
end
end
my user model is like this
def apply_omniauth(omniauth)
self.email = omniauth['user_info']['email'] if email.blank?
authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'])
end
def password_required?
(authentications.empty? || !password.blank?) && super
end
My authentications controller is like this
class AuthenticationsController < ApplicationController
def index
#authentications = current_user.authentications if current_user
end
def create
omniauth = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
if authentication
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
else
user = User.new
user.apply_omniauth(omniauth)
if user.save
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omniauth.except('extra')
redirect_to new_user_registration_url
end
end
end
def destroy
#authentication = current_user.authentications.find(params[:id])
#authentication.destroy
flash[:notice] = "Successfully destroyed authentication."
redirect_to authentications_url
end
protected
# This is necessary since Rails 3.0.4
# See https://github.com/intridea/omniauth/issues/185
# and http://www.arailsdemo.com/posts/44
def handle_unverified_request
true
end
end
My registration controller is like this
class RegistrationsController < Devise::RegistrationsController
def create
super
session[:omniauth] = nil unless #user.new_record?
end
private
def build_resource(*args)
super
if session[:omniauth]
#user.apply_omniauth(session[:omniauth])
#user.valid?
end
end
end
Inside your app/models/authentication.rb add this
def self.find_by_provider_and_uid(provider, uid)
where(provider: provider, uid: uid).first
end
Did you add this in your model? If not added then add this and then try
key :provider, String
key :uid, String

Resources