Login or Register (Ruby on rails)

Posted by DanielZ on Stack Overflow See other posts from Stack Overflow or by DanielZ
Published on 2011-01-02T23:22:05Z Indexed on 2011/01/03 6:53 UTC
Read the original article Hit count: 204

Hello stackoverflow,

I'm working on an Ruby on Rails application (2.3.x) and i want to make a form that lets the user login or register. I want to do this in the same form. I have a JS function that replaces the form elements like this:

Login form:

<% form_for @user do |f| %>
<div id="form">
    <%= f.label :email, "E-mail" %>
    <%= f.text_field :email %>

    <%= f.label :password, "Password" %>
    <%= f.password_field :password %>

    <%= link_to "I don't have an account, "#", :id => "changeForm"%>
    <%= f.submit "Login" %>
</div>
<% end %>

The id "changeForm" triggers a JS function that changes the form elements. So if you press the url the html looks like this:

<% form_for @user do |f| %>
<div id="form">
    <%= f.label :name, "Name" %>
    <%= f.text_field :name %>

    <%= f.label :email, "E-mail" %>
    <%= f.text_field :email %>

    <%= f.label :password, "Password" %>
    <%= f.password_field :password %>

    <%= f.label :password_confirmation, "Password confirmation" %>
    <%= f.password_field :password_confirmation %>

    <%= link_to "I do have an account, "#", :id => "changeForm"%>
    <%= f.submit "Register" %>
</div>
<% end %>

I added the neccesary validations to my user model:

class User < ActiveRecord::Base
    attr_reader :password
    validates_presence_of :name, :email, :password
    validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
    validates_confirmation_of :password   

But what happens when you fill in the email / password you get the errors that the name is missing and that the password fields aren't confirmed. So i could do some nasty programming in my user model like this:

#if password_conf or the name are present the user has tried to register...
if params[:user][:password_confirmation].present? || params[:user][:name].present?
   #so we'll try to save the user
   if @user.save
     #if the user is saved authenticate the user
     current_session.user = User.authenticate(params[:user])
     #if the user is logged in?
     if current_session.user.present?
       flash[:notice] = "succesvully logged
       redirect_to some_routes_path
     else
       #not logged in...
       flash[:notice] = "Not logged in"  
       render :action => "new"            
     end
   else
     #user not saved
     render :action => "new"
   end
 else
   #So if the params[:user][:password_confirmation] or [:user][:name] weren't present we geuss the user wants to login...
   current_session.user = User.authenticate(params[:user])
     #are we logged_in?
     if current_session.user.present?
       flash[:notice] = "Succesvully logged in"
       redirect_to some_routes_path
     else
       #errors toevoegen    
       @user.errors.add(:email, "The combination of email/password isn't valid")
       @user.errors.add(:password," ")
       render :action => "new"
     end
 end
end

Without validations this (imho dirty code and should not be in the controller) works. But i want to use the validates_presence_of methods and i don't want to slap the "conventions over configurations" in the face.

So another thing i have tried is adding a hidden field to the form:

    #login form
    <%= f.hidden_field :login, :value => true %>
    # and ofcourse set it to false if we want to register.

And then i wanted to use the method: before_validation

before_validation_on_create do |user|
  if params[:user].login == true #throws an error i know...
      validates_presence_of :email, :password
      validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
  else
    validates_presence_of :name, :email, :password
    validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
    validates_confirmation_of :password        
  end
end

But this doesn't work because i can't access the params. And login isn't a attribute for the user object. But i thought that in this way i could validate the email and password params if the user wants to login. And all the other attrs if the user want to register.

So all i could think of doesn't work how i want it to work. So my main goal is this:

1 form for login/register with the use of the validation methods in the user model. So if we want to login but don't fill in any information => give validation errors. And if the user wants to login but the email/password combination doens't match give the "@user.errors.add(:email, "the combination wasn't found in the db...")". And the same goes for user register...

Thanks in advance!

© Stack Overflow or respective owner

Related posts about ruby-on-rails

Related posts about ruby