I'm having issues loading a new registration page using Devise in my rails app. When I try to load the sign up page, I get the error:
undefined method `errors' for nil:NilClass
which seems to be caused by the following line:
<%= devise_error_messages! %>
What could I be doing wrong?
routes.rb:
devise_for :users, :controllers => {:registrations => :registrations, omniauth_callbacks: "users/omniauth_callbacks"}
devise_scope :user do
post 'registrations' => 'registrations#create', :as => 'register'
post 'sessions' => 'sessions#create', :as => 'login'
delete 'sessions' => 'sessions#destroy', :as => 'logout'
end
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
# GET /user/sign_up
def new
build_resource({})
respond_with self.resource
end
The sign up link:
<%= link_to "Sign Up", new_registration_path(resource_name), :class=>"btn btn-mini", :style=>'float:left'%>
application_helper.rb (where resource_name is defined)
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
the sign up view
<div class="signUpPage">
<div class="form_container">
<h3 class="form_heading sign_up">Sign up</h3>
<%= semantic_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="formField"><%= f.label :username, :class=> "label label-info" %><br />
<%= f.text_field :username, :class=> "signup_username", :maxlength=>"15"%></div>
<div class="usernameValidation validation">Username is already taken</div>
<div class="formField"><%= f.label :email, :class=> "label label-info" %><br />
<%= f.email_field :email%></div>
<div class="emailValidation validation">Email is already taken</div>
<div class="formField"><%= f.label :password, :class=>"label label-info" %><br />
<%= f.password_field :password, :class=> "signup_password" %></div>
<div class="passwordValidation validation">Password must be at least 8 characters</div>
<div class="formField"><%= f.label :password_confirmation, :class=>"label label-info" %><br />
<%= f.password_field :password_confirmation %></div>
<div class="passwordConfirmationValidation validation">Passwords do not match</div>
<div><%= f.submit "Sign up", :class=>"btn btn-info signup_button" %></div>
<% end %>
<%= render "devise/shared/links" %>
</div>
</div>
This is the full error message:
NoMethodError in Registrations#new
Showing Website/app/views/devise/registrations/new.html.erb where line #12 raised:
undefined method `errors' for nil:NilClass
Extracted source (around line #12):
9:
10: <%= semantic_form_for(resource, :as => resource_name, :url => registration_path(resource_name), namespace: 'sign_up', html: {id: 'form_user_sign_up'}) do |f| %>
11:
12: <%= devise_error_messages! %>
13:
14: <div class="formField"><%= f.label :username, :class=> "label label-info" %><br />
15: <%= f.text_field :username, :class=> "signup_username", :maxlength=>"15"%></div>
Rails.root: /Website
app/views/devise/registrations/new.html.erb:12:in `block in _app_views_devise_registrations_new_html_erb___65153715043208623_70149577578880'
app/views/devise/registrations/new.html.erb:10:in `_app_views_devise_registrations_new_html_erb___65153715043208623_70149577578880'
app/controllers/registrations_controller.rb:11:in `new'
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 keep getting the following error on my app from 7.2.1 on Michael Hartl Ruby Rails tutorial. For some reason it is not accepting a nil #user field in the signup form.
undefined method `users_path' for #<#<Class:0x007ff87141aef8>:0x007ff870cf0d30>
new.html.erb
<% provide(:title, "Sign up") %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
User_controller.rb
class UserController < ApplicationController
def new
#user = User.new
end
def show
#user = User.find(params[:id])
end
end
Routes.rb
Rails.application.routes.draw do
resources :user
get 'user/new'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'user#new'
You need to change resources :user to resources :users and define the index action in the controller by adding
def index
end
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
I use devise for rails 3.2 for authentication. I've changed the default routes from devise to:
devise_scope :user do
get 'signin' => 'devise/sessions#new', :as => :new_user_session
post 'signin' => 'devise/sessions#create', :as => :user_session
match 'signout' => 'devise/sessions#destroy', :as => :destroy_user_session,
:via => Devise.mappings[:user].sign_out_via
end
Now my sign in and sign up form is on the root site. How can I avoid to access 127.0.0.1:3000/signin but grant access to only 127.0.0.1:3000
when i remove it, i will get an error message like this
oMethodError in Authentication#welcome
Showing /Volumes/Develop/login_app/app/views/authentication/welcome.html.erb where line #6 raised:
undefined method `user_session_path' for #<ActionDispatch::Routing::RoutesProxy:0x007ffb4d711a10>
Extracted source (around line #6):
i have sign_in und sign_up on the root site..looks like this
<h1>Hello</h1>
<h2>Sign in</h2>
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= f.submit "Sign in" %></div>
<% end %>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end -%>
<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 %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
now somebody can come and put 127.0.0.1/signin in the url and then it will show the sign_in form, i will avoid this, because it should show on the root site...
the same scenario like sing_up...
thanks
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| %>