I\'m using Devise in a Rails 3 app, but in this case, a user must be created by an existing user, who determines what permissions he/she will have.
Because of this, I
You can override the "devise_scope" by placing it before the "devise_for".
devise_scope :user do
get "/users/sign_up", :to => "sites#index"
end
devise_for :users
Not sure if this is the best way but its my solution currently, as it just redirects back to the sign in page.
I found another post similar to this one and wanted to share an answer @chrisnicola gave. In the post they were attempting to only block user signup's during production.
You could also modify the registrations controller. You can use something like this:
In "app/controllers/registrations_controller.rb"
class RegistrationsController < Devise::RegistrationsController
def new
flash[:info] = 'Registrations are not open.'
redirect_to root_path
end
def create
flash[:info] = 'Registrations are not open.'
redirect_to root_path
end
end
This will override devise's controller and use the above methods instead. They added flash messages incase that someone somehow made it to the sign_up page. You should also be able to change the redirect to any path you like.
Also in "config/routes.rb" you can add this:
devise_for :users, :controllers => { :registrations => "registrations" }
Leaving it like this will allow you to use the standard devise edit your profile. If you wish you can still override the edit profile option by including
def update
end
in the "app/controllers/registrations_controller.rb"
I had the same issue and I found it a bit bad practise to redirect users from the registration page. So my solution is basically is not using :registrable at all.
What I did was to create a similar page like edit user details which looked like:
<%= form_tag(update_user_update_path, method: :post) do %>
<br>
<%= label_tag(:currPassword, 'Current password:') %> <%= password_field_tag(:currPassword) %> <br>
<%= label_tag(:newPassword, 'New password:') %> <%= password_field_tag(:newPassword) %> <br>
<%= label_tag(:newPasswordConfirm, 'Confirm new password:') %> <%= password_field_tag(:newPasswordConfirm) %> <br>
<%= submit_tag('Update') %>
<% end %>
So this form submits into a new post end point that updates the password, which looks like:
def update
currPass = params['currPassword']
newPass1 = params['newPassword']
newPass2 = params['newPasswordConfirm']
currentUserParams = Hash.new()
currentUserParams[:current_password] = currPass
currentUserParams[:password] = newPass1
currentUserParams[:password_confirmation] = newPass2
@result = current_user.update_with_password(currentUserParams)
end
Later on you can use the @result in your view to tell the user whether the password is updated or not.
Do This in routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
devise_scope :user do
get "/sign_in", :to => "devise/sessions#new"
get "/sign_up", :to => "devise/registrations#new"
end
you will get an error now while you come to sign in page, to fix it. Do this change in: app/views/devise/shared/_links.erb
<% if request.path != "/sign_in" %>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
<% end %>
you can do this in your model
# typical devise setup in User.rb
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
change it to:
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
notice that the symbol :registerable was removed
That's it, nothing else is required. All routes and links to registration page are magically removed too.
I liked @max's answer, but when trying to use it I ran into an error due to devise_mapping being nil.
I modified his solution slightly to one that seems to address the issue. It required wrapping the call to resource inside devise_scope.
devise_for :users, skip: [:registrations]
devise_scope :user do
resource :users,
only: [:edit, :update, :destroy],
controller: 'devise/registrations',
as: :user_registration do
get 'cancel'
end
end
Note that devise_scope expects the singular :user whereas resource expects the plural :users.