I have 2 different devise registration forms, one for normal users and another for vendors, well I created a custom registrations controller and it is correctly working:
class RegistrationsController < Devise::RegistrationsController
def create
super
if resource.save
if params[:role] == 'vendedor'
resource.add_role :vendedor
end
end
end
#In this action I render the custom form for vendors registration
def new_with_role
build_resource({})
case params[:role]
when 'proveedor'
else
redirect_to root_path, alert: 'Unexpected error'
end
end
end
I created this route for the custom form for vendors:
devise_scope :user do
get "/sign_up/:role" => 'registrations#new_with_role', as: 'new_user_with_role'
end
And this is the form views/devise/registrations/new_with_role.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), builder: FoundationFormBuilder) do |f| %>
<%= f.text_field :name, label: "Company name", autofocus: true %>
<%= f.email_field :email, label: "Correo electrónico(ideal: Gmail, Hotmail, Outlook, Yahoo)" %>
<%if @validatable %>
<%= f.password_field :password, autocomplete: "off", hint: "#{@minimum_password_length} caracteres como mínimo" %>
<% else %>
<%= f.password_field :password, autocomplete: "off" %>
<% end %>
<%= f.password_field :password_confirmation, label: "Confirmar contraseña", autocomplete: "off" %>
<%= hidden_field_tag :role, 'vendedor' %> #With this custom param I can set the role of the user in the create action of the custom registrations controller
<%= f.submit "Enviar", data: { disable_with: "Wait please..." } %>
<% end %>
The form works great, however I can't figure out how to render the errors in this custom form, When I send the form with intentional errors I get the following:
undefined method `errors' for nil:NilClass
Checking the logs I could find that when there are errors the create
action of my RegistrationsController
is rendering the new
action of Devise, and I think that is causing the error, I want to render the new_with_role
action if there is an error filling its form.
These are the logs when I send the form for vendors with intentional mistakes:
Started POST "/users" for ::1 at 2016-02-01 15:33:36 -0500
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"kwiV0+GwiGTYVQf0iFE19YoZqZKnAgqzGkTr3D9OCYy03ZPy7xC4ZjFSlnfItE4fuofRAg9jMJ3wIN+si8oR+w==", "user"=>{"last_name"=>"", "phone1"=>"", "first_name"=>"", "email"=>"", "preference_details"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "business_line"=>"2", "role"=>"vendedor", "commit"=>"Enviar"}
(0.4ms) BEGIN
User Exists (1.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY '' LIMIT 1
(0.3ms) ROLLBACK
Rendered devise/registrations/new.html.erb within layouts/application (84.1ms)
Completed 500 Internal Server Error in 224ms (ActiveRecord: 2.1ms)
ActionView::Template::Error (undefined method `errors' for nil:NilClass):
11: <% end %>
12: <h5 class="subtitle">O regístrate de la forma tradicional</h5>
13: <%= form_for(:user, as: resource_name, url: registration_path(resource_name), builder: FoundationFormBuilder) do |f| %>
14: <%= f.text_field :first_name, label: "Nombre", autofocus: true %>
15: <%= f.text_field :last_name, label: "Apellido" %>
16: <%= f.email_field :email, label: "Correo electrónico" %>
17: <div class="row collapse">
lib/foundation_form_builder.rb:75:in `errors_on?'
lib/foundation_form_builder.rb:21:in `block (2 levels) in <class:FoundationFormBuilder>'
app/views/devise/registrations/new.html.erb:14:in `block in _app_views_devise_registrations_new_html_erb__4160932045667554001_70342326706100'
app/views/devise/registrations/new.html.erb:13:in `_app_views_devise_registrations_new_html_erb__4160932045667554001_70342326706100'
app/controllers/registrations_controller.rb:3:in `create'
Rendered /Users/sebastianvelandiagiraldo/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/_source.erb (9.4ms)
Rendered /Users/sebastianvelandiagiraldo/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (4.2ms)
Rendered /Users/sebastianvelandiagiraldo/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (2.0ms)
Rendered /Users/sebastianvelandiagiraldo/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (43.8ms)
As you can see when there are errors on the form the rendered action is:
Rendered devise/registrations/new.html.erb
it should be:
Rendered devise/registrations/new_with_role.html.erb
I guess that's causing the issue. Any help would be very appreciated
I found this issue that is similar, but the answer provided there is useless.
Code of the create action of my current Devise version 3.5.2 as requested
def create
build_resource(sign_up_params)
resource.save
yield resource if block_given?
if resource.persisted?
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_format?
sign_up(resource_name, resource)
respond_with resource, location: after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
set_minimum_password_length
if params[:role].present?
render :new_with_role
else
respond_with resource
end
end
end
The form submit action of your custom view is create action:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), builder: FoundationFormBuilder) do |f| %>
and the action does not tell to render new view in case of error. There isn't any code that mentions that. So either call a custom submit action that renders the custom view in case of error, or instead of calling super, change action code based on some param to render different templates.
If you want a cleaner approach, use the devise json API from your custom views via ajax calls. Here is a link for how you can use the API: http://blog.andrewray.me/how-to-set-up-devise-ajax-authentication-with-rails-4-0/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.