I am building a simple app that allows members to create a trip. Only one trip. I wanted to get some practice using the devise gem so that setting up the application with sign in, sign out, etc is easy and efficient, but I need some help. Right now I have two models: member & trip, neither of which have a controller.
This is my sign up form and when I click submit, somehow a member is created in the database even without a member controller? How do I redirect this to a different page after submit is pressed?
I'm just a little confused on what I should be adding since devise is doing a lot of the work behind the scenes.
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
You create a controller to do this.
class UserController < Application::Base
def new
#user = User.new
end
def create
#user = User.new(email: params[:email], password: params[:password], password_confirmation: params[:password_confirmation])
if #user.save
redirect_to <page you want to redirect to>
else
render new
end
end
The user(or in you case member) controller simply talking resides in devise gem internals.
To redirect a user to user/home you may define user_root route in your routes.rb file in this way:
get 'user/home', as: 'user_root'
Read more here.
Devise offers some macros that you can override to choose what paths you want to redirect to.
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path'
end
end
Source
EDIT:
Create a file in your controller folder called registrations_controller.rb. Put this code into that file.
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path'
end
end
Replace /an/example/path with whatever path you want to redirect to after someone signs up. Then modify your config/routes.rb to point to that controller by adding this line:
devise_for :members, :controllers => { :registrations => "registrations" }
Then, you may need to edit your config/application.rb by adding this line
config.paths['app/views'] << "app/views/devise"
If you encounter a "MissingTemplate" error.
Related
I am using devise and the views file is /devise/registrations/edit.html.erb (I have not made any changes to it):
<div><%= f.label :password %>
<%= f.password_field :password, :autocomplete => "off" %></div>
<div><%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %></div>
<% if f.object.encrypted_password.present? %>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<% end %>
<div><%= f.submit "Update" %></div>
When the user changes their password, they are getting redirected to root_url (homepage). I want to keep them at the change password page, which is /users/edit. How can I do it?
EDIT - I do have registration_controller with edit method, what should I add in it ?
The update action in PasswordsController calls a protected method named after_resetting_password_path_for.
The method just calls after_sign_in_path_for so I think it should be safe to subclass PasswordsController and override this method.
It looks like there's is already a test for whent this method is overridden so it looks like it's definitely supported.
First, OP have problem about redirect after change password, change password in devise is in the RegistrationsController, while PasswordsController for "Reset Password". FYI #amesee's answer for redirect after reset password. Change password and reset password are differents
How To: Customize the redirect after a user edits their profile and see after_update_path_for(resource)
You should add after_update_path_for(resource) method on your registrations_controller.rb looks like :
class RegistrationsController < Devise::RegistrationsController
protected
def after_update_path_for(resource)
root_path
end
end
If you have different model for User and Admin, you need this:
routes.rb
devise_for :admins, controllers: {registrations: 'admins/registrations'}, defaults: { format: 'html' }
app/controllers/admins/registration_controller.rb
class Admins::RegistrationsController < Devise::RegistrationsController
def after_update_path_for(resource)
after_change_password_path # change this
end
end
i create controller:
class SigninController < ApplicationController
def index
end
def create
#user = User.find_by_email(params[:user][:email])
if #user
....
sign_in(:user, #user)
else
#user = User.new(params...)
#user.save
...
end
end
end
Correctly i call sign_in method?
signin/index.html.erb:
<h2>Sign in</h2>
<%= form_for(User.new, :as => :user, :url => "signin") do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<br>
<div><%= f.submit "Sign in" %></div>
<% end %>
How to call devise sign_in and sign_up methods of devise?
Try this in app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
def after_create_path_for(resource)
sign_in(:user, resource)
end
end
That's just kind of a guess. I don't know if it will work.
You may but in most cases you should not create custom controller to sign in / out user. Devise has sessions_controller which implements this functionality for you. View devise documentation and wiki, it has plenty of documentation. Also you can found out there how to customise views and controller behaviour.
Update
If need to place both forms (login and registrations) on one view you can customise devise view. Form actions may point to different standard controllers. I suggest to use users/registrations/new form for base form and add uses/sessions/new form to it.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Is this a good approach to continue developing a ruby on rails web application?
here is a signup sample:
user model: user.rb
class User < ActiveRecord::Base
attr_accessible :email, :name, :password, :username
validates_presence_of :email, :name, :password, :username
end
signup controller: signup-controller.rb
class SignupController < ApplicationController
def init
#user = User.new
render :template => '/signup/signup'
end
def signup
#user = User.new(params[:user])
if #user.valid?
#user.save
render :template => '/signup/success'
else
#bla bla bla
end
end
end
signup page: signup.html.erb
<h1>Signup!!!</h1>
<%= form_for(#user, :url => signup_path) do |f| %>
Name: <%= f.text_field :name %> </br>
Email <%= f.text_field :email %> </br>
Username: <%= f.text_field :username %> </br>
Password: <%= f.text_field :password %> </br>
<%= submit_tag "Submit" %>
<% end %>
after signup process complete: success.html.erb
<h1>signup successfull :) </h1>
routes.rb
get '/index/signup' => 'signup#init', :as => :signup_index
post '/index/signup/' => 'signup#signup', :as => :signup
Michael Durrant has given some great advice that I'll be careful not to copy. However, there are some things that I would like to add that are more code specific.
Preparing for Rails 4.0
I'm assuming this is either a practice application or something that is early on in development. Regardless of which is true for you, I think you'll be better off if you go ahead an adopt some of the new changes in Rails 4.0.
One of the new changes is Strong Parameters. Rails will be dropping the use of attr_accessible in the model and creating a new way of dealing with mass-assignment in the controller. This will allow you to "dynamically" change which fields can be updated depending on different users or namespaces.
Updating the code you have written so far isn't very difficult. I've gone ahead and made the key changes myself.
Gemfile
gem 'strong_parameters'
user model: user.php
class User < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
validates_presence_of :email, :name, :password, :username
end
users controller: users_controller.php
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to login_path, :notice => "You have signed up successfully. You may now login!"
else
render :new, :alert => "There was an problem creating your account"
end
end
private
def user_params
params.require(:user).permit(:email, :name, :password, :username)
end
end
Note: I made some changes to users_controller.php other than using strong parameters.
I changed the action names to match the Rails resource verbs.
Instead of calling .valid? and .save, I changed the if statement to only use .save. This is because .save will call .valid? and return false accordingly.
I modified/added redirect_to and render calls to the create action. The redirect_to call is a more important change because it helps prevent double form submission.
Using a Partial for your Forms
One of the cool features of working with views in Rails are partials. A partial allows you to extract a snippet of HTML that is used in more than one place. By using a partial you can write the code for your form_for in one file and use it in the new and edit actions. Keeping your code DRY.
Also, I noticed that you didn't use the <label> tag in your form. This is something that I think is very important because it improves user experience.
Note: I've changed the signup page filename to match the changes in my version of users_controller.php.
signup page: new.html.erb
<h1>Signup!!</h1>
<%= render :partial => "form" %>
user form: _form.html.erb
<%= form_for #user do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br />
<%= f.label :email, "Email Address" %>
<%= f.email_field :email %><br />
<%= f.label :username %>
<%= f.text_field :username %><br />
<%= f.label :password %>
<%= f.password_field :password %><br />
<%= f.submit "Sign Up" %>
<% end %>
If you have any questions to something I've posted please ask. I'll try to explain anything I can.
Getting rails right is all about following its conventions.
Change init to new
Change signup to create.
use resources :users for routes.
Even better follow a railscast on using authLogic or Devise rather than rolling your own.
Using Devise and wanting the user to go to a specific page after they sign up. Here's the kicker; the user can either sign up as a Buyer or a Worker via radio button. When they sign up as a Worker, I want them to go to a specific path.
So far, the code I have now, a Buyer and Worker will both go to the same path. The 'current_user.worker?' code is what I think is not working right.
new.html.erb
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= radio_button_tag 'user[role]', 'worker' %>
<%= radio_button_tag 'user[role]', 'buyer' %>
<%= f.text_field :username %>
<%= f.email_field :email %>
<%= f.password_field :password %>
<%= f.password_field :password_confirmation %>
<%= f.submit 'Create Account', :class => 'button' %>
<% end %>
application_controller.rb
class ApplicationController < ActionController::Base
def after_sign_up_path_for(resource_or_scope)
if current_user.worker?
account_setup_path
else
end
end
end
Add the following to your user.rb .. assuming you have a column in your users table called "role" and it's either "worker" or "buyer".
def worker?
(self.role == "worker")
end
def buyer?
(self.role == "buyer")
end
Then this should work after signup... put it in the same controller as your signup code (Most likely RegistrationController?)
def after_sign_up_path_for(resource_or_scope)
account_setup_path if current_user.worker?
some_other_path if current_user.buyer?
# And if they are not a buyer or worker .. well. Redirect to root.
root_path
end
(Also make sure you have the latest version of Devise)
Devise gem is used for authentication. I need to have a user index and show view. Found this how to at the devise wiki, however played around, can not make it work.
Devise - How To: Manage users through a CRUD interface
Method 1: Remember to remove the :registerable module from the Devise model (in my case it was the User model) Make sure to put your map.resources :users below the map.devise_for :users route (devise_for :users and resources :users for Rails 3).
Method 2: devise_for :users, :path_prefix => ādā resources :users to isolate the devise logic from your crud user controlle
My question:
1. if you remove registerable in the model, then how does devise work for user?
2. If you done this, can you provide a sample?
Thanks in advance
The following worked for me.
users_controller.rb
class UsersController < ApplicationController
...
def create
#user = User.new(params[:user])
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
respond_to do |format|
if #user.save
format.html { redirect_to users_path, notice: 'User was successfully created.' }
else
format.html { render action: "new" }
end
end
end
...
end
routes.rb
...
devise_for :users, :path_prefix => 'd'
resources :users
...
I hope this can help you.
Regards,
Giacomo
By placing the appropriate new.html.erb, edit.html.erb, _form.html.erb etc files in the User Views folder, adding/editing/deleting Users should work no differently as any other CRUD, as Devise's User is another model like any. I won't post the new or edit erbs (simple enough, and a scaffold can show you the rest), but an example of my User _form.html.erb...
<%= form_for(#user) do |f| %>
<%= render :partial => 'shared/errors', :locals => { :content => #user } %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In mine, I think I left :registerable in and I'm still able to administer and update users via the CRUD. If you leave it out, then users can't register themselves, but you can still add and edit users yourself (would protect the Users controller with load_and_authorize_resource to keep regular users out, of course).