Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise. Registration and Login at the same page

I'm trying to integrate Devise into my application. I need implement login form at top of the page (I've implemented this form into layout page) and I've implemented registration which contains registration form. But it shows validation errors for both form when I tried submit incorrect registration data.

like image 859
Vitaly Aksionchyk Avatar asked May 23 '11 12:05

Vitaly Aksionchyk


2 Answers

Without more information, it's hard to guess what the problem is. I've found the Wiki pages to be really helpful (and increasingly so), though you may have already looked them over:

Devise Wiki Pages

Two pages that might be relevant to your needs:

Display a custom sign_in form anywhere in your app

Create custom layouts

Hope this helps!

-- ff

like image 126
fearless_fool Avatar answered Oct 12 '22 23:10

fearless_fool


The problem of seeing the validation errors for both forms stems from the 2 things. First, devise forms use a generic 'resource' helper. This creates a User object, and that same user objet gets used for both the sign up and the sign in form. Second, devise errors are typically displayed using the 'devise_error_messages!' helper which uses that same shared resource.

To have sign in and sign up on the same page you need to create different user objects for each form, and a new way of displaying the error messages.

First off, you'll need to create your own registration controller (in app/controllers/users/)

class Users::RegistrationsController < Devise::RegistrationsController
  include DevisePermittedParameters

  protected

  def build_resource(hash=nil)
    super
    # Create an instance var to use just for the sign up form
    @sign_up_user = self.resource
  end
end

And update your routes file accordingly

devise_for :users, controllers: {
  registrations: 'users/registrations'
}

Next you'll need your own error messages and resource helpers. Create a new helper like devise_single_page_helper.rb and add the following:

module DeviseSinglePageHelper
  def devise_error_messages_for_same_page(given_resource)
    return "" if given_resource.errors.empty?

    messages = given_resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
    sentence = I18n.t("errors.messages.not_saved",
                      count: given_resource.errors.count,
                      resource: given_resource.class.model_name.human.downcase)

    html = <<-HTML
  <div id="error_explanation">
    <h2>#{sentence}</h2>
    <ul>#{messages}</ul>
  </div>
    HTML

    html.html_safe
  end

  def sign_up_user
    @sign_up_user ||= User.new(username: 'su')
  end

  def sign_in_user
    @sign_in_user ||= User.new(username: 'si')
  end
end

Finally, in your views, update your forms like so:

  -# The sign up form
  = simple_form_for(sign_up_user, url: registration_path(resource_name)) do |f|
    -#...
    = devise_error_messages_for_same_page(sign_up_user)


  -# The sign in form
  = simple_form_for(sign_in_user, url: sessions_path(resource_name)) do |f|
    #...
    = devise_error_messages_for_same_page(sign_in_user)

All of this together gives you 2 different objects - 1 for sign up and 1 for sign in. This will prevent the error messages from one showing in the other. Please note that recommend putting both forms on your sign in page (and perhaps having the default sign up page redirect to the sign in page) because by default a failed sign in attempt will redirect to the sign in page.

like image 33
Geoff Evason Avatar answered Oct 12 '22 22:10

Geoff Evason



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!