new to Rails here. I am wondering if anyone can help me with the problem that I am having. So basically, I am trying to use devise to add user authentication to my app. But every time I tried to submit the signup form, a warning "No route matches [POST] "users/sign_up"" appears on the app.
Here are my routes.rb
Rails.application.routes.draw do
get 'home/index'
root 'home#index'
#devise_for :users, controllers: { sessions: 'user/sessions' }
devise_for :users, path: 'auth', path_names:
{ sign_in: 'login', sign_out: 'logout', password: 'secret', confirmation: 'verification',
unlock: 'unblock', registration: 'register', sign_up: 'cmon_let_me_in' }
devise_scope :user do
get 'sign_in', to: 'devise/sessions#new'
end
resources :workspaces do
resources :items
end
end
Also, my new.html.erb on the devise/registration looks like:
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: new_user_registration_path) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "users/shared/links" %>
Thank you for your help.
Related
I used devise inthe login system.I want create two new html under the registrations, which is two different roles' pages. And I want to go to that page by choosing roles in registrations/new, which is the original signup file. What should I do next?
my files order in the view/user/registrations: enter image description here.
edit.html.erb
new.html.erb
new_librarian.html.erb
new_student.html.erb
I want to signup in the new two pages through registrations/new
<!-- what i changed in the registrations/new -->
<h2>Sign up</h2>
<p>Sign up as a Student<%= link_to 'Student', users_registrations_new_student_path, :method => 'get' %></p>
<p>Sign up as a Librarian<%= link_to 'Librarian', users_registrations_new_librarian_path, :method => 'get'%></p>
<!-- what is in the registrations/new_student -->
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", adminv: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :select_role %><br />
<%= f.collection_select :role, User::ROLES, :to_s, :humanize %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<!-- what i changed in the routes.rb -->
get 'users/registrations/new_librarian'
get 'users/registrations/new_student'
Could not find devise mapping for path "/users/registrations/new_student". This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example: devise_scope :user do get "/some/route" => "some_devise_controller" end
2) You are testing a Devise controller bypassing the router. If so, you can explicitly tell Devise which mapping to use: #request.env["devise.mapping"] = Devise.mappings[:user]
You can achieve this by overriding the devise registration controller. In your overrided registration controller, in the new method once the user is saved,
#app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
if #user.save!
if #user.role == "librarian"
redirect_to librarian_profile_path
elsif #user.role == "student"
redirect_to student_profile_path
end
end
end
end
You can define librarian_profile_path and student_profile_path in your routes
#app/config/routes.rb
get 'librarian/new' => 'librarian_profile#new', :as => 'librarian_profile'
get 'student/new' => 'student_profile#new', :as => 'student_profile'
I'm working on a Rails 5.2 project with two Devise models (Admin and User). I've followed the suggestion on this Stack Overflow answer to disable sign-ups for a Devise model without breaking Devise's edit_admin_registration_path.
After applying the changes suggested in routes.rb, running rails routes shows the changes working as expected, however when going to edit an Admin (edit_admin_registration_path), i get the error:
NoMethodError in Admins::RegistrationsController#edit
undefined method `validatable?' for nil:NilClass
I suspect the issue is that the linked answer was not using multiple Devise models with scoped views and controllers.
Any ideas?
I've added this to routes.rb:
devise_scope :admin do
get "/sign_in" => "admins/sessions#new" # custom path to login/sign_in
get "/sign_up" => "admins/registrations#new", as: "new_admin_registration" # custom path to sign_up/registration
end
devise_for :admins, skip: [ :registrations ], path: 'admins', controllers: { sessions: 'admins/sessions', registrations: 'admins/registrations' }
as :admins do
get 'admins/edit' => 'admins/registrations#edit', as: 'edit_admin_registration'
put 'admins' => 'admins/registrations#update', as: 'admin_registration'
end
Form on view:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), method: :put) do |f| %>
<%= devise_error_messages! %>
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-control" %>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
<% if #minimum_password_length %>
<em><%= #minimum_password_length %> characters minimum</em>
<% end %>
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "off", class: "form-control" %>
<%= f.submit "Update", class: "btn btn-success" %>
<% end %>
Answer found:
Routes needed to be configured like so (as can be found in this Stack Overflow answer):
devise_for :admins, :skip => [:registrations], path: 'admins', controllers: { sessions: 'admins/sessions', registrations: 'admins/registrations' }
devise_scope :admin do
get 'admins/edit' => 'admins/registrations#edit', as: 'edit_admin_registration'
put 'admins' => 'admins/registrations#update', as: 'admin_registration'
end
I incorporated devise in my user model but when i try to sign up someone i get this error No route matches [POST] "/users/sign_up.user"
I have the devise views and controllers in my app too. But when i click the sign up button i get that error.
this is my routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: "users/registrations" }
#resources :users
#resources :admin
devise_scope :user do
root :to => 'devise/sessions#new'
end
end
and this is my form
Sign up
<%= form_for(resource, as: resource_name, url: new_user_registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if #validatable %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "users/shared/links" %>
I had this exact same problem, and struggled with what was up for a while. My solution might not have anything to do with your particular case, but worth a try.
In my view I had used erb's button_to tag to hit the new_user_registration_path:
<%= button_to 'Sign up', new_user_registration_path %>
this was sending a POST request when the route is a GET request. Changing the button_to tag to a link_to tag solved it:
<%= link_to 'Sign up', new_user_registration_path %>
Since you changed the route to:
devise_for :users, controllers: { registrations: "users/registrations" }
There's no need for the resource in the path you're using in your form. Simply take it out and it should look like this:
<%= form_for(resource, as: resource_name, url: new_user_registration_path) do |f| %>
My problem with devise.
I want to save private data of user without current_password.
And I want to remove some routes, leaving only the necessary.
routes.rb
devise_for :users, :controllers => { :registrations => "registrations" }, :skip => [:registrations]
as :user do
post "/users" => "devise/registrations#create", :as => :user_registration
get "/users" => "devise/registrations#new", :as => :new_user_registration
get "/users/edit" => "devise/registrations#edit", :as => :edit_user_registration
put "/users" => "devise/registrations#update"
end
I watched railscasts and add Registrations controller in my application
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def update
#user = User.find(current_user.id)
# email_changed = #user.email != params[:user][:email]
password_changed = !params[:user][:password].empty?
successfully_updated = if password_changed
#user.update_with_password(params[:user])
else
#user.update_without_password(params[:user])
end
if successfully_updated
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
end
My view edit.html.erb
<h2><%= t('users.edit_registration_data') %></h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<ul class="nav nav-tabs">
<li class="active" ><%= t('tabs.private_info') %></li>
<li><%= t('tabs.change_password') %></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="profile">
<div><%= f.label :name, t('form.name') %><br />
<%= f.text_field :name %></div>
<div><%= f.label :phone_number, t('form.phone_number') %> <%= t('form.phone_notice' )%><br />
<%= f.text_field :phone_number, :maxlength => 10 %></div>
<div><%= f.label :area_id, t('form.area') %><br />
<%= f.text_field :area_id %></div>
<div><%= f.label :city_id, t('form.city') %><br />
<%= f.text_field :city_id %></div>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
</div>
<div class="tab-pane" id="password">
<div><%= f.label :password, t('users.form.new_password') %> <i>(<%= t('users.notifications.leave_password') %>)</i><br />
<%= f.password_field :password, :autocomplete => "off" %></div>
<div><%= f.label :password_confirmation, t('users.form.new_password_confirmation') %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :current_password, t('users.form.current_password') %> <i>(<%= t('users.notifications.need_current_password') %>)</i><br />
<%= f.password_field :current_password %></div>
</div>
</div>
<br><br><br>
<div><%= f.submit t('users.update') %></div>
<% end %>
<%= link_to t('users.back'), :back %>
But when I update any data, except for the password, the application still asks for the current password.
controller: devise/registrations
action: update
1 error prohibited this user from being saved: Current password can not be empty
devise_for :users, :skip => [:registrations]
as :user do
post "/users" => "devise/registrations#create", :as => :user_registration
get "/users" => "devise/registrations#new", :as => :new_user_registration
get "/users/edit" => "devise/registrations#edit", :as => :edit_user_registration
put "/users" => "registrations#update"
end
This error tells me - undefined method 'user_profiles_path', while my routes are like 'user_profile_path'. Profile is a singleton child resource of users. Not sure what is causing this error. The error is raised by <%= form_for [#user, #profile] do |f| %> in _form.html.erb.
Routes.rb:
devise_for :users, :path_names => { :sign_in => "login", :sign_up => "register" } do
get "/login", :to => "devise/sessions#new"
get "/register", :to => "devise/registrations#new"
get "/logout", :to => "devise/sessions#destroy"
get '/account' => 'devise/registrations#edit'
end
root :to => "questions#redirect_on_visit"
match 'home', :to => "questions#index"
resources :questions do
resources :question_responses
end
resources :users do
resource :profile
end
_form.html.erb:
<%= form_for [#user, #profile] do |f| %>
<%= f.error_messages %>
<div class="field">
<%= f.label :display_name, "Display Name" %><br />
<%= f.text_field :display_name, :size => "43" %><br />
</div>
<div class="field">
<%= f.label :current_location, "Current Location" %><br />
<%= f.text_field :current_location, :size => "43" %><br />
</div>
<div><%= f.label :nationality, "Nationality" %><br />
<%= f.collection_select :nationality, Profile::NATIONALITY, :include_blank => true %>
</div><br />
<div><%= f.label :home_place, "Home Place" %><br />
<%= f.collection_select :home_place, Profile::HOME_PLACE, :include_blank => true %>
</div><br />
<div><%= f.label :occupation, "Occupation" %><br />
<%= f.collection_select :occupation, Profile::OCCUPATION, :include_blank => true %>
</div><br />
<div><%= f.label :interest, "Interests" %><br />
<%= f.collection_select :interest, Profile::INTERESTS, :include_blank => true %>
</div><br />
<div><%= f.label :hobby, "Hobbies" %><br />
<%= f.collection_select :hobby, Profile::HOBBIES, :include_blank => true %>
</div><br />
<div class="field">
<%= f.label :bio, "Short Bio" %><br />
<%= f.text_area :bio, :size => "50x5" %>
</div>
<div class="submit">
<%= f.submit "Create Profile" %>
</div>
<% end %>
profiles_controller.rb:
class ProfilesController < ApplicationController
before_filter :find_user
def new
#profile = #user.build_profile
end
def edit
end
private
def find_user
#user = User.find(params[:user_id])
end
end
application.html.erb:
<% if user_signed_in? %>
<% if !current_user.try(:profile) %>
Signed in as<div><%= link_to current_user.email, new_user_profile_path(current_user.id) %></div><br /><br />
<% else %>
Signed in as<div><%= link_to current_user.email, edit_user_profile_path(current_user.id) %></div><br /><br />
<% end %>
Not you? <%= link_to "Sign out", logout_path %>
<% else %>
<%= link_to "Sign up", new_user_registration_path %> or <%= link_to "Sign in", new_user_session_path %>
<% end %>
Routes:
user_profile POST /users/:user_id/profile(.:format) profiles#create
new_user_profile GET /users/:user_id/profile/new(.:format) profiles#new
edit_user_profile GET /users/:user_id/profile/edit(.:format) profiles#edit
GET /users/:user_id/profile(.:format) profiles#show
PUT /users/:user_id/profile(.:format) profiles#update
DELETE /users/:user_id/profile(.:format)
Okay this error is a known bug as reported here: https://github.com/rails/rails/issues/1769
And I found the right way to specify URL.
form_for([#user, #profile], url: user_profile_path(#user))
Syntactically important to have braces and important that there is no space between form_for and parenthesis.
You can correct this by manually specifying the URL in the form:
<%= form_for [#user, #profile], :url => user_profile_path(#user) do |f| %>