10
votes

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 %>
4
I'd suggest an admin interface gem such as Rails Admin or Active Admin to manage users.Joe Kennedy
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_pathsp1rs
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
sp1rs, can you clarify what you mean by creating a credential? Is that something that devise provides?Shazam
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

4 Answers

19
votes

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).

8
votes

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.

0
votes

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.

0
votes

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.