I want my user to be able to go straight to the path subscriptions/new after landing on their edit user/update account page. can anyone help me as to how i would go about this. I have listed my routes below
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :line1, :line2, :town, :county, :postcode, :password, :password_confrimation, :current_password)}
end
private
def after_sign_in_path_for(resource)
edit_user_registration_path(current_user) #basically whichever path you think meets your needs
end
routes.rb file
Rails.application.routes.draw do
resources :subscriptions, only: [:new, :create, :show, :destroy]
#gives standard routes
get 'content/fruit'
get 'content/veg'
get 'content/mix'
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
namespace :admin do
get 'dashboard/index'
end
devise_for :users, :controllers => {:registrations => 'devise/registrations'}
# devise_for :users
resources :products do
resources :orders, only: [:new, :create]
#tells rails needs product id number
end
# get 'pages/payment'
get 'home/about'
get 'home/contact'
get 'seller' => "products#seller"
get 'sales' => "orders#sales"
get 'static_pages/productlanding'
get "content/veg"
get "content/fruit"
get "content/mix"
get 'subscriptions/new'
Devise Registration Controller
class Devise::RegistrationsController < DeviseController
def update
set_flash_message :notice, :"message here" if is_flashing_format?
session[:user_return_to] = new_subscription_path
super
end
end
Edit form user
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :avatar, class: 'col-sm-2 control-label' %>
<div class="col-sm-6">
<%= f.file_field :avatar %>
</div>
</div>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: "form-control" %>
</div>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div class="form-group">
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
</div>
<% end %>
<div class="form-group">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i>
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i>
<%= f.password_field :current_password, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :line1 %>
<%= f.text_field :line1, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :line2 %>
<%= f.text_field :line2, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :town %>
<%= f.text_field :town, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :county %>
<%= f.text_field :county, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :postcode %>
<%= f.text_field :postcode, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :organization %>
<%= f.text_field :organization, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit "Update", class: "btn btn-primary" %>
</div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= button_to "cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete, class: "btn btn-danger" %></p>
<%= link_to "Back", :back %>
You can change path on this method after_update_path_for(resource)
class Devise::RegistrationsController < DeviseController
## other devise stuff
protected
def after_update_path_for(resource)
new_subscription_path
end
end
If you have multiple devise model you can try this
class Devise::RegistrationsController < DeviseController
## other devise stuff
protected
def after_update_path_for(resource)
if resource.is_a?(DeviseModel1)
new_subscription_path
else
other_path
end
end
end
Or you can put them into application_controller.rb
You need to override update action of devise registration controller for this.
class Devise::RegistrationsController < DeviseController
def update
set_flash_message :notice, :"message here" if is_flashing_format?
session[:user_return_to] = new_subscription_path
super
end
end
In your routes :
devise_for :users, :controllers => {:registrations => 'devise/registrations'}
There should be another controller app/controllers/devise/registrations. Controller code above.
If you want to make custom message then it come from config/locales/en.yml:
en:
devise:
registrations:
destroyed: "my custom message."
updated: "my custom message"
Related
it is my login application .please anyone can explain me how can i check login validations
pbl01/config/routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => {
:registrations => 'users/registrations'
}
resources :import,only: [:index,:create]
root 'root#index'
# For details on the DSL available within this file, see
http://guides.rubyonrails.org/routing.html
end
pbl01/app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
before_action :configure_sign_in_params, only: [:create]
def new
end
def create
authorized_user=User.authenticate(params[:userid],params[:password])
if authorized_user
flash[:notice] = "Wow Welcome again, you logged in as"
else
flash[:notice] = "Invalid Username or Password"
flash[:color]= "invalid"
render "new"
end
end
pbl01/app/models/user.rb
require 'csv'
class User < ApplicationRecord
validates :userid, :presence => true,
validates :password, :presence => true,
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
def email_required?
false
end
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
users = find_by(userid: row["userid"]) || new
users.attributes = row.to_hash.slice(*updatable_attributes)
users.password= row["password"]
users.save!
end
end
def self.updatable_attributes
["userid", "name", "email"]
end
end
pbl01/app/views/devise/sessions/new.html.erb
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<% if #user.errors.any? %>
<div class="field">
<%= f.label :userid %><br />
<%= f.text_field :userid, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "off" %>
<% for message_error in #user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</div>
<% if devise_mapping.rememberable? -%>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end -%>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
I believe you should change to something like this.
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url:
session_path(resource_name)) do |f| %>
<% if #user.errors.any? %>
<% for message_error in #user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
<% end %>
<div class="field">
<%= f.label :userid %><br />
<%= f.text_field :userid, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<% if devise_mapping.rememberable? -%>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
I am using carrierwave and minimagick gem to save user for picture uploads in Rails. I have added picture field to the the devise forms and updated the User model to include the mountuploader file.
However, when I try to save, the users attributes are all saved and updated in the database except for the picture.
When I check the User in the console, picture attribute is nil . Any ideas ? My other models save the picture just fine.
Here are my devise forms:
devise_registerations/new
<div class="authform">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :role => 'form', multipart: true}) do |f| %>
<h3>Sign up</h3>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :country %>
<%= country_select(resource_name, "country")%>
</div>
<div class="form-group">
<%= f.label :description, "Bio" %>
<%= f.text_area :description, class: 'form-control', cols: "30", rows: "10" %>
</div>
Picture: <%= f.file_field :picture %>
<%= f.submit 'Sign up', :class => 'button right' %>
<% end %>
</div>
My edit is similar:
<div class="authform">
<h3>Edit <%= resource_name.to_s.humanize %></h3>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put, :role => 'form', multipart: true }) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
</div>
<fieldset>
<p>Leave these fields blank if you don't want to change your password.</p>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, :autocomplete => 'off', class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
</fieldset>
<fieldset>
<p>You must enter your current password to make changes.</p>
<div class="form-group">
<%= f.label :current_password %>
<%= f.password_field :current_password, class: 'form-control' %>
</div>
</fieldset>
Picture: <%= f.file_field :picture %>
<%= f.submit 'Update', :class => 'button right' %>
<% end %>
</div>
<div class="authform">
<h3>Cancel Account</h3>
<p>Unhappy? We'll be sad to see you go.</p>
<%= button_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete, :class => 'button right' %>
</div>
Here is my UsersController :
class UsersController < ApplicationController
before_action :authenticate_user!
before_action :admin_only, :except => :show
def index
#users = User.all
end
def show
#user = User.find(params[:id])
unless (current_user.admin? || current_user == #user)
unless #user == current_user
redirect_to :back, :alert => "Access denied."
end
end
end
def update
#user = User.find(params[:id])
if #user.update_attributes(secure_params)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
user = User.find(params[:id])
user.destroy
redirect_to users_path, :notice => "User deleted."
end
private
def admin_only
unless current_user.admin?
redirect_to :back, :alert => "Access denied."
end
end
def secure_params
params.require(:user).permit(:role, :picture, :name, :email, :password)
end
end
And finally I am including my UserModel:
class User < ActiveRecord::Base
enum role: [:user, :vip, :admin, :manager]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
mount_uploader :picture, PictureUploader
has_many :projects, dependent: :destroy
end
I think I am in the right path:
https://github.com/carrierwaveuploader/carrierwave/wiki/how-to:-use-carrierwave-with-devise
I'm making a Rails app and am trying to have the user's role displayed on a view. The code I am using for this is:
<%= current_user.role %>
Which does not evaluate to anything.
I am using devise for user registrations and my registration view is as follows:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="login-field">
<%= f.email_field :email, :placeholder => "Email" %>
</div>
<div class="login-field">
<%= f.password_field :password, autocomplete: "off", :placeholder => "Password (8 character min)" %>
</div>
<div class="login-field">
<%= f.text_field :firstname, :placeholder => "First Name" %>
</div>
<div class="login-field">
<%= f.text_field :lastname, :placeholder => "Last Name" %>
</div>
<div class="login-field">
<%= f.text_field :phone, :placeholder => "Phone Number" %>
</div>
<%= f.select(:role, ['Role 1', 'Role 2', 'Both']) %>
<br>
<div><%= f.submit "Signup" , :class => "btn btn-success btn-lg" %></div>
<% end %>
<%= render "devise/shared/links" %>
I have a feeling that I am doing something wrong in the form submission but cannot figure out what it is. Any help is appreciated
You can put this at the top of your create action:
return render text: params.inspect # get what the form sended
and or
return render text: create_params # get what the values you permitted
This way you will get what the data your from sended and if it is what you expected.
You should override the sign_up_params in the Devise registration. Once you've created your RegistrationsController that inherits from Devise::RegistrationsController, you can override the sign_up_params:
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:first_name, :last_name, :email, :phone, :role ... any other attributes)
end
end
You would also need to change you routes.rb to point to the newly created controller:
devise_for :users, controllers: {registrations: 'registrations'}
Happy Thursday everyone, I had a quick question on routes and redirecting. I am working on a rails assignment that asks that I redirect the router to his/her profile after signing in. How would I go about doing that? An after_sign_in method? Here is my routes:
Rails.application.routes.draw do
devise_for :users
resources :users
get 'welcome/index'
root :to => 'welcome#index'
end
Users Controller:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:name, :email)
end
end
devise/sessions (Login Page)
<h2>Sign in</h2>
<div class="row">
<div class="col-md-8">
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, autofocus: true, class: 'form-control', placeholder: "Enter email" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control', placeholder: "Enter password" %>
</div>
<div class="form-group">
<% if devise_mapping.rememberable? %>
<%= f.label :remember_me, class: 'checkbox' do %>
<%= f.check_box :remember_me %> Remember me
<% end %>
<% end %>
<%= f.submit "Sign in", class: 'btn btn-success' %>
</div>
<div class="form-group">
<%= render "devise/shared/links" %>
</div>
<% end %>
</div>
</div>
Application Controller
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
def after_sign_in_path_for(resource)
user_show_path
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
end
end
I tried defining a after_sign_in_path in the application controller but recieve this error: undefined local variable or method `user_show_path'
The URL helper you need to call is user_path(resource) instead of user_show_path. (Devise will pass the current user as the resource for you.)
Check out the Rails guide on routing for details about the helpers that are generated when using resources in your routes.
I worry the solution here will be woefully obvious, but I'm having trouble implementing the instructions on the Devise wiki (https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-edit-their-account-without-providing-a-password)
I'm using Rails 4. After following the wiki, I'm still receiving "current password can't be blank". Here's my setup. Any assistance is much appreciated!
REGISTRATIONS_CONTOLLER.rb
class RegistrationsController < Devise::RegistrationsController
def update
#user = User.find(current_user.id)
successfully_updated = if needs_password?(#user, params)
#user.update_with_password(devise_parameter_sanitizer.for(:account_update))
# Rails 3: #user.update_with_password(params[:user])
else
# remove the virtual current_password attribute update_without_password
# doesn't know how to ignore it
params[:user].delete(:current_password)
#user.update_with_password(devise_parameter_sanitizer.for(:account_update))
# Rails 3: #user.update_without_password(params[:user])
end
if successfully_updated
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
redirect_to after_update_path_for(#user)
else
render "edit"
end
end
private
# check if we need password to update user data
# ie if password or email was changed
# extend this as needed
def needs_password?(user, params)
user.email != params[:user][:email] ||
params[:user][:password].present?
end
end
APPLICATION_CONTROLER.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:account_update) do |u|
u.permit(:first_name, :last_name, :username, :email, :avatar, :password, :password_confirmation)
end
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name, :username, :email, :password, :password_confirmation)
end
devise_parameter_sanitizer.for(:sign_in) do |u|
u.permit(:username, :email, :password)
end
end
end
ROUTES.rb
ProjectFoo::Application.routes.draw do
devise_for :users, :controllers => { :registrations => "registrations",
:invitations => 'users/invitations' }
Note: I'm also using the devise_invitable gem
VIEWS/DEVISE/REGISTRATIONS/EDIT.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= image_tag #user.avatar.url(:square) %>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put, :class => 'form-horizontal' }) do |f| %>
<%= devise_error_messages! %>
<div class="span5">
<div class="control-group">
<%= f.label :email, :class => 'control-label' %>
<div class="controls">
<%= f.email_field :email, :autofocus => true, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :username, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :username, :autofocus => true, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :first_name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :first_name, :autofocus => true, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :last_name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :last_name, :autofocus => true, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :twitter_handle, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :twitter_handle, :autofocus => true, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :avatar, :class => 'control-label' %>
<div class="controls">
<%= f.file_field :avatar, :class => 'file_field' %>
</div>
</div>
</div>
<div class="span5">
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div class="control-group">
<%= f.label :password, :class => 'control-label' %>
<div class="controls">
<%= f.password_field :password, :autocomplete => "off", :class => 'password_field' %><br><i>(leave blank if you don't want to change it)</i>
</div>
</div>
<div class="control-group">
<%= f.label :password_confirmation, :class => 'control-label' %>
<div class="controls">
<%= f.password_field :password_confirmation, :class => 'password_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :current_password, :class => 'control-label' %>
<div class="controls">
<%= f.password_field :current_password, :class => 'password_field' %><p><i>(we need your current password to confirm your changes)</i></p>
</div>
</div>
<%= f.submit "Update" %>
</div>
<% end %>
<div class="span11">
<hr>
</div>
<div class="span11">
<h3>Cancel my account</h3>
<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %></p>
<p><%= link_to "Back", :back %></p>
</div>
You have update_with_password twice. The second time should be update_without_password.
I had same problem for hours. In my particular situation I had many custom user attributes that could be updated from different partials. Make sure you at least add hidden fields - name and email - as required by needs_password?