11

I am using Ruby On Rails with Devise, Rails 4.1.0.rc1, Ruby 2.1.0p0, devise-3.2.4

I followed the tutorial from Rails Cast Episode #209 to get devise installed and working. I can login and log out and register new users.

I extended my user model to include non-changing information like birthdate, first name and last name.

Following this blog post I added a user controller & views in order to add additional functionality such as a listing of all users that I did not see with devise. https://github.com/danweller18/devise/wiki/Allow-Users-to-View-Profile-and-List-All-Users

I have also reviewed these questions on Stack overflow: Allowing admins to add users with Devise How do I customize the controller for registration in Devise? Ruby on Rails: Custom Devise Registration Controller, Asking For Create Action

I am new to ruby on rails since March 1st of this year, and have taken Mike & Nicole Clarks Rails 1 & Rails 2 online courses.

What I am trying to do is allow a user to add new users. Ultimately this function would be an admin or manager adding clients. The client should then be able to log in with the credentials created.

What is occurring is that I can be logged in, add a new "user" through the new_user_path and user view (as opposed to the devise view) but when I submit it, I am then logged in as the new user. The previous users is not persistent.

I am doing all of this via the users view & controller actions because I don't want to actually "register" or login & logout with these actions, just create new records in the user table that would then be able to log in on their own.

Any help is appreciated.

here is my user controller:

class UsersController < ApplicationController

    def index
        @users = User.all
    end

    def show
      @user = User.find_by_id(params[:id])
    end

    def new
        @user = User.new
    end

    def edit
        @user = User.find(params[:id])
    end

    def update
        @user = User.find(params[:id])
        if @user.update_attributes(user_params)
            redirect_to user_url, notice: "Updated User."
        else
            render :edit
        end
    end

    def create
        @user = User.new(user_params)
        if @user.save
            redirect_to user_url, notice: "User succesfully created!" 
        else
            render :new
        end
    end






private

def user_params
  params.require(:user).permit(:first_name, :last_name, :img_file_name, :email, :password, :password_confirmation, :birthdate)
end
end

Here is my 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?


protected

    def configure_permitted_parameters
        devise_parameter_sanitizer.for(:account_update) {|u| 
            u.permit(:first_name, :last_name, :birthdate, :img_file_name, :email, :password, :password_confirmation, :current_password)}
        devise_parameter_sanitizer.for(:sign_up) {|u| 
            u.permit(:first_name, :last_name, :birthdate, :img_file_name, :email, :password, :password_confirmation, :current_password)}
    end




end

Here is my user new.html.erb file: (Admins Only is just a reminder for me right now, there is no admin function at them moment)

<header id="content-header">
  <h1>Create a New User (Admins Only)</h1>
</header>

<%= render 'form' %>

Here is the _form.html.erb

<%= form_for(@user) do |f| %>
  <%= render "shared/errors", object: @user %>
  <fieldset>
    <ol>

      <li class="required">
        <%= f.label :first_name %>
        <%= f.text_field :first_name, size: 40, autofocus: true %>
      </li>
      <li class="required">
        <%= f.label :last_name %>
        <%= f.text_field :last_name, size: 40 %>
      </li>
      <li class="required">
        <%= f.label :email %>
        <%= f.email_field :email, size: 40 %>
      </li>
      <li class="required">
        <%= f.label :password %>
        <%= f.password_field :password, size: 40 %>
      </li>
      <li class="required">
        <%= f.label :password_confirmation, "Confirm Password" %>
        <%= f.password_field :password_confirmation, size: 40 %>
      </li>
      <li >
        <%= f.label :birthdate %><br/>
        <%= f.date_select :birthdate, start_year: 1915 %><br/>
      </li>

      <li >
          <%= f.label :img_file_name %><br/>
          <%= f.text_field :img_file_name %>
      </li>

    </ol>
    <p>
      <% if @user.new_record? %>
        <%= f.submit "Create Account" %>
      <% else %>
        <%= f.submit "Update Account" %>
      <% end %>
      <%= link_to "Cancel", users_path, class: 'button' %>
    </p>
  </fieldset>
<% end %>
Community
  • 1
  • 1
Shazam
  • 301
  • 1
  • 2
  • 16
  • I'd suggest an admin interface gem such as [Rails Admin](https://github.com/sferik/rails_admin) or [Active Admin](https://github.com/gregbell/active_admin) to manage users. – Joe Kennedy Apr 17 '14 at 17:58
  • In create action ..after saving just check that the admin has created a credential or the user has created a credential .. if admin has created a credential then save it and redirect to admin_path else redirect to user_path – sp1rs Apr 17 '14 at 17:58
  • Either u can use rails admin gem or create a action in your controller admin_only and add constraint to it .. and in your controller add before_save :admin_only ... – sp1rs Apr 17 '14 at 18:00
  • sp1rs, can you clarify what you mean by creating a credential? Is that something that devise provides? – Shazam Apr 17 '14 at 18:05
  • I'll look into the Rails admin gem, but I would like to understand why what I am doing will or won't work. Thanks all. – Shazam Apr 17 '14 at 18:06
  • @Shazam credential means save the user details in db.. Instead of using rails admin gem .. i would prefer creating your own action in user controller and allow access of new , create action to admin only .. it will give u more flexibility .. – sp1rs Apr 17 '14 at 18:28
  • @sp1rs, aha! so do you think that in this line here: redirect_to user_url, notice: "User succesfully created!" I am telling it to go to the user I JUST created? That could be the ticket! Now I understand your first comment and it makes sense to have the admin function there. Thanks. – Shazam Apr 18 '14 at 04:41

4 Answers4

20

I think the problem is actually with your routes. I imagine that you've added resources :users to your routes file to set up routes for your UsersController. However, I'm guessing that you've also got devise_for :users … to set up devise. This means that you'll have devise and your UsersController fighting for the same routes. Specifically, you're expecting a POST to /users to create a new user, but it's actually routing to devise's RegistrationsController and registering a new user and signing them in.

You can see this by running rake routes and seeing that both devise and your UsersController have, for example, mappings for POST /users(.:format). You need to separate out the two sets of routes. There are various ways you can do this. You could add :path => 'u' to your devise_for line in routes.rb, which will then mean your devise routes are all /u instead of /users. Alternatively, you could keep devise routes on /users and instead change your UsersController routes to something like:

resources :users_admin, :controller => 'users'

which will map /users_admin to your UsersController (but note the path helpers will also change from e.g. users_path to users_admin_path).

Tim
  • 2,903
  • 2
  • 18
  • 16
  • Tim I think you are exactly right. This and the comment by sp1rs above. I havn't "solved" it yet, but I will go in and change the routes and see how that goes. This part is still a bit new to me and what you describe is clear. I was worried about that but didn't know how to go about investigating it or changing it. I would like to vote up your answer but d o not have enough "reputation" to do so yet. – Shazam Apr 20 '14 at 20:59
  • I found it simpler to namespace the device routes, rather than branching my standard user routes. (Permission to create and delete users will be handled by roles...pundit in my case...not by routing complexity! All I had to do was change `devise_for :users, controllers: {confirmations: 'confirmations'}` to `devise_for :users, :path => 'auth', controllers: {confirmations: 'confirmations'}` and it Just Worked™. Thanks, Tim! – clozach Nov 06 '14 at 09:40
  • This should be in the wiki. the current article is v unpleasant – Will Apr 25 '18 at 15:05
10

Here is what I finally did to solve this

in routes.rb

  devise_for :users  
  resources :users_admin, :controller => 'users'

in users_controller.rb no changes

in form.html.erb for adding new & updating users. Note the specified URL. This is documented to some degree here, but only mentions it for singular resources http://guides.rubyonrails.org/routing.html

However I had to separate out the edit & new paths as the url would not work in both create & update at the same time, so instead of rendering a partial, I just have 2 forms. Not sure what the workaround is.

This one is my new user form:

<%= form_for @user, url: users_admin_index_path(@user)  do |f| %> 

And this one is in my edit user form:

<%= form_for @user, url: users_admin_path(@user)  do |f| %>  

At the bottom of the form I have this code:

 <% if @user.new_record? %>
        <%= f.submit "Create Account" %>
      <% else %>
        <%= f.submit "Update Account" %>
      <% end %>
      <%= link_to "Cancel", users_admin_index_path, class: 'button' %>
    </p>

Then in the show.html.erb form I had to specify the URLS from 'rake routes'

<footer>
  <nav>
    <%= link_to "Edit User", edit_users_admin_path, class: 'button' %> |
    <%= link_to "New User", new_users_admin_path, class: 'button' %> | 
    <%= link_to "All Users", users_admin_index_path, class: 'button' %>
  </nav>
</footer>

I got the path names from rake routes.

I hope this helps somebody else out and thank you all for the help. I do not have enough reputation to upvote any answers yet.

Shazam
  • 301
  • 1
  • 2
  • 16
  • I pretty much follow what you did but now I confronted a problem: Whenever a user is created by an admin, the current user switches to the newly created user. Does that happen to you? – TimeString May 10 '16 at 23:04
0

As i understood your question(text part, not read the code), you want users to add other users and the accounts should be ready to be used. TO register using devise, you would be using user email, password and password_confirmation field as mandatory.

When registering users with email, provide a dummy password to the accounts so that the user entry is being saved. Send mails to the users to confirm their account and change password using the password reset links.

Bijendra
  • 9,467
  • 8
  • 39
  • 66
  • Ghost Rider, that functionality is already working. But what is happening is that when the new user is added by the existing user, the existing user is logged out and the new user is logged in. I want the existing user to remain the existing user. – Shazam Apr 17 '14 at 23:42
  • that must be some flaw in the code flow, when adding users what u need to do is call the create method and create a user entry and send a mail to user at the same time. It's just crud operation and should not be responsible for destroying session. Check for before_filters or any code which calls redirect method. – Bijendra Apr 18 '14 at 13:33
  • Thanks Ghost Rider. I think I've got it figured out, my routes were interacting with one another, I think I was able to leave the controller as is. Thank you because this helped me trouble shoot that the session should not be affected by crud. – Shazam Apr 21 '14 at 00:31
0

GhostRider is correct on the workflow. You could also move the logic to an AdminsController or similar. This thread will solve the specific issue of getting signed in as that user: Devise: How to create a new user being already logged in?

But it is a better workflow to have the admin set a temporary password and email the new user to have them finish creating their account.

Community
  • 1
  • 1
Jim Wrubel
  • 4,031
  • 1
  • 17
  • 12